diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..ed4609fb18 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,35 @@ +# +# see https://help.github.com/articles/dealing-with-line-endings/ +# + +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to Unix line endings on checkout. +*.c text eol=lf +*.cpp text eol=lf +*.h text eol=lf +*.xml text eol=lf +*.mk text eol=lf +*.java text eol=lf +*.bat text eol=lf +*.sh text eol=lf +*.iml text eol=lf +*.txt text eol=lf +*.yaml text eol=lf +*.ini text eol=lf +*.input text eol=lf +*.rules text eol=lf + +# KiCad files +*.dsn text eol=lf +*.kicad_pcb text eol=lf +*.net text eol=lf +*.pro text eol=lf +*.sch text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary + diff --git a/os/hal/ports/STM32/LLD/ADCv1/driver.mk b/os/hal/ports/STM32/LLD/ADCv1/driver.mk index a3b76492a7..b0d340498d 100644 --- a/os/hal/ports/STM32/LLD/ADCv1/driver.mk +++ b/os/hal/ports/STM32/LLD/ADCv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1 diff --git a/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c index a8733f9340..e2076fb4ca 100644 --- a/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c +++ b/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c @@ -1,485 +1,485 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv1/hal_adc_lld.c - * @brief STM32 ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define ADC1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) - -/* Headers differences patches.*/ -#if defined(ADC_IER_AWDIE) && !defined(ADC_IER_AWD1IE) -#define ADC_IER_AWD1IE ADC_IER_AWDIE -#endif - -#if defined(ADC_ISR_AWD) && !defined(ADC_ISR_AWD1) -#define ADC_ISR_AWD1 ADC_ISR_AWD -#endif - -#define TR1 TR - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief ADC voltage regulator enable. - * - * @param[in] adc pointer to the ADC registers block - */ -NOINLINE static void adc_lld_vreg_on(ADC_TypeDef *adc) { - - osalDbgAssert(adc->CR == 0, "invalid register state"); - -#if defined(ADC_CR_ADVREGEN) - adc->CR = ADC_CR_ADVREGEN; - volatile uint32_t loop = (STM32_HCLK >> 20) << 4; - do { - loop--; - } while (loop > 0); -#else -#endif -} - -/** - * @brief Stops an ongoing conversion, if any. - * - * @param[in] adc pointer to the ADC registers block - */ -static void adc_lld_stop_adc(ADC_TypeDef *adc) { - - if (adc->CR & ADC_CR_ADSTART) { - adc->CR |= ADC_CR_ADSTP; - while (adc->CR & ADC_CR_ADSTP) - ; - adc->IER = 0; - } -} - -/** - * @brief ADC DMA service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -#if !defined(STM32_ADC1_HANDLER) -#error "STM32_ADC1_HANDLER not defined" -#endif -/** - * @brief ADC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - adc_lld_serve_interrupt(&ADCD1); - -#if defined(STM32_ADC_ADC1_IRQ_HOOK) - STM32_ADC_ADC1_IRQ_HOOK -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = NULL; - 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; - - /* The vector is initialized on driver initialization and never - disabled.*/ - nvicEnableVector(12, STM32_ADC_ADC1_IRQ_PRIORITY); -#endif - - /* Calibration procedure.*/ - rccEnableADC1(true); - - /* CCR setup.*/ -#if STM32_ADC_SUPPORTS_PRESCALER - ADC->CCR = STM32_ADC_PRESC << 18; -#else - ADC->CCR = 0; -#endif - - /* Regulator enabled and stabilized before calibration.*/ - adc_lld_vreg_on(ADC1); - - ADC1->CR |= ADC_CR_ADCAL; - while (ADC1->CR & ADC_CR_ADCAL) - ; - ADC1->CR = 0; - rccDisableADC1(); -} - -/** - * @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) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - rccEnableADC1(true); - - /* DMA setup.*/ - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1); -#endif - - /* Clock settings.*/ - adcp->adc->CFGR2 = STM32_ADC_ADC1_CKMODE; - } -#endif /* STM32_ADC_USE_ADC1 */ - - /* Regulator enabled and stabilized before calibration.*/ - adc_lld_vreg_on(ADC1); - - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->adc->CR = ADC_CR_ADEN; - while (!(adcp->adc->ISR & ADC_ISR_ADRDY)) - ; - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - - /* Restoring CCR default.*/ -#if STM32_ADC_SUPPORTS_PRESCALER - ADC->CCR = STM32_ADC_PRESC << 18; -#else - ADC->CCR = 0; -#endif - - /* Disabling ADC.*/ - if (adcp->adc->CR & ADC_CR_ADEN) { - adc_lld_stop_adc(adcp->adc); - adcp->adc->CR |= ADC_CR_ADDIS; - while (adcp->adc->CR & ADC_CR_ADDIS) - ; - } - - /* Regulator and anything else off.*/ - adcp->adc->CR = 0; - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC1(); -#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, cfgr1; - const ADCConversionGroup *grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - cfgr1 |= ADC_CFGR1_DMACFG; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup, if it is defined a callback for the analog watch dog then it - is enabled.*/ - adcp->adc->ISR = adcp->adc->ISR; - adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE; - adcp->adc->TR1 = grpp->tr; - adcp->adc->SMPR = grpp->smpr; - adcp->adc->CHSELR = grpp->chselr; - - /* ADC configuration and start.*/ - adcp->adc->CFGR1 = cfgr1; -#if STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE - { - uint32_t cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK; - adcp->adc->CFGR2 = cfgr2 | grpp->cfgr2; - } -#endif - - /* ADC conversion start.*/ - adcp->adc->CR |= ADC_CR_ADSTART; -} - -/** - * @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); - adc_lld_stop_adc(adcp->adc); -} - -/** - * @brief ISR code. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_serve_interrupt(ADCDriver *adcp) { - uint32_t isr; - - isr = adcp->adc->ISR; - adcp->adc->ISR = isr; - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - /* 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 ((isr & ADC_ISR_OVR) && - (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); - } - if (isr & ADC_ISR_AWD1) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD); - } - } -} - -/** - * @brief Enables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVREF(ADCDriver *adcp) { - - (void)adcp; - - ADC->CCR |= ADC_CCR_VREFEN; -} - -/** - * @brief Disables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVREF(ADCDriver *adcp) { - - (void)adcp; - - ADC->CCR &= ~ADC_CCR_VREFEN; -} - -/** - * @brief Enables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableTS(ADCDriver *adcp) { - - (void)adcp; - - ADC->CCR |= ADC_CCR_TSEN; -} - -/** - * @brief Disables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableTS(ADCDriver *adcp) { - - (void)adcp; - - ADC->CCR &= ~ADC_CCR_TSEN; -} - -#if defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__) -/** - * @brief Enables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVBAT(ADCDriver *adcp) { - - (void)adcp; - - ADC->CCR |= ADC_CCR_VBATEN; -} - -/** - * @brief Disables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVBAT(ADCDriver *adcp) { - - (void)adcp; - - ADC->CCR &= ~ADC_CCR_VBATEN; -} -#endif /* defined(ADC_CCR_VBATEN) */ - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv1/hal_adc_lld.c + * @brief STM32 ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define ADC1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) + +/* Headers differences patches.*/ +#if defined(ADC_IER_AWDIE) && !defined(ADC_IER_AWD1IE) +#define ADC_IER_AWD1IE ADC_IER_AWDIE +#endif + +#if defined(ADC_ISR_AWD) && !defined(ADC_ISR_AWD1) +#define ADC_ISR_AWD1 ADC_ISR_AWD +#endif + +#define TR1 TR + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief ADC voltage regulator enable. + * + * @param[in] adc pointer to the ADC registers block + */ +NOINLINE static void adc_lld_vreg_on(ADC_TypeDef *adc) { + + osalDbgAssert(adc->CR == 0, "invalid register state"); + +#if defined(ADC_CR_ADVREGEN) + adc->CR = ADC_CR_ADVREGEN; + volatile uint32_t loop = (STM32_HCLK >> 20) << 4; + do { + loop--; + } while (loop > 0); +#else +#endif +} + +/** + * @brief Stops an ongoing conversion, if any. + * + * @param[in] adc pointer to the ADC registers block + */ +static void adc_lld_stop_adc(ADC_TypeDef *adc) { + + if (adc->CR & ADC_CR_ADSTART) { + adc->CR |= ADC_CR_ADSTP; + while (adc->CR & ADC_CR_ADSTP) + ; + adc->IER = 0; + } +} + +/** + * @brief ADC DMA service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +#if !defined(STM32_ADC1_HANDLER) +#error "STM32_ADC1_HANDLER not defined" +#endif +/** + * @brief ADC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + adc_lld_serve_interrupt(&ADCD1); + +#if defined(STM32_ADC_ADC1_IRQ_HOOK) + STM32_ADC_ADC1_IRQ_HOOK +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = NULL; + 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; + + /* The vector is initialized on driver initialization and never + disabled.*/ + nvicEnableVector(12, STM32_ADC_ADC1_IRQ_PRIORITY); +#endif + + /* Calibration procedure.*/ + rccEnableADC1(true); + + /* CCR setup.*/ +#if STM32_ADC_SUPPORTS_PRESCALER + ADC->CCR = STM32_ADC_PRESC << 18; +#else + ADC->CCR = 0; +#endif + + /* Regulator enabled and stabilized before calibration.*/ + adc_lld_vreg_on(ADC1); + + ADC1->CR |= ADC_CR_ADCAL; + while (ADC1->CR & ADC_CR_ADCAL) + ; + ADC1->CR = 0; + rccDisableADC1(); +} + +/** + * @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) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + rccEnableADC1(true); + + /* DMA setup.*/ + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1); +#endif + + /* Clock settings.*/ + adcp->adc->CFGR2 = STM32_ADC_ADC1_CKMODE; + } +#endif /* STM32_ADC_USE_ADC1 */ + + /* Regulator enabled and stabilized before calibration.*/ + adc_lld_vreg_on(ADC1); + + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->adc->CR = ADC_CR_ADEN; + while (!(adcp->adc->ISR & ADC_ISR_ADRDY)) + ; + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + + /* Restoring CCR default.*/ +#if STM32_ADC_SUPPORTS_PRESCALER + ADC->CCR = STM32_ADC_PRESC << 18; +#else + ADC->CCR = 0; +#endif + + /* Disabling ADC.*/ + if (adcp->adc->CR & ADC_CR_ADEN) { + adc_lld_stop_adc(adcp->adc); + adcp->adc->CR |= ADC_CR_ADDIS; + while (adcp->adc->CR & ADC_CR_ADDIS) + ; + } + + /* Regulator and anything else off.*/ + adcp->adc->CR = 0; + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC1(); +#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, cfgr1; + const ADCConversionGroup *grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + cfgr1 |= ADC_CFGR1_DMACFG; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup, if it is defined a callback for the analog watch dog then it + is enabled.*/ + adcp->adc->ISR = adcp->adc->ISR; + adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE; + adcp->adc->TR1 = grpp->tr; + adcp->adc->SMPR = grpp->smpr; + adcp->adc->CHSELR = grpp->chselr; + + /* ADC configuration and start.*/ + adcp->adc->CFGR1 = cfgr1; +#if STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE + { + uint32_t cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK; + adcp->adc->CFGR2 = cfgr2 | grpp->cfgr2; + } +#endif + + /* ADC conversion start.*/ + adcp->adc->CR |= ADC_CR_ADSTART; +} + +/** + * @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); + adc_lld_stop_adc(adcp->adc); +} + +/** + * @brief ISR code. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_serve_interrupt(ADCDriver *adcp) { + uint32_t isr; + + isr = adcp->adc->ISR; + adcp->adc->ISR = isr; + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + /* 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 ((isr & ADC_ISR_OVR) && + (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); + } + if (isr & ADC_ISR_AWD1) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD); + } + } +} + +/** + * @brief Enables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVREF(ADCDriver *adcp) { + + (void)adcp; + + ADC->CCR |= ADC_CCR_VREFEN; +} + +/** + * @brief Disables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVREF(ADCDriver *adcp) { + + (void)adcp; + + ADC->CCR &= ~ADC_CCR_VREFEN; +} + +/** + * @brief Enables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableTS(ADCDriver *adcp) { + + (void)adcp; + + ADC->CCR |= ADC_CCR_TSEN; +} + +/** + * @brief Disables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableTS(ADCDriver *adcp) { + + (void)adcp; + + ADC->CCR &= ~ADC_CCR_TSEN; +} + +#if defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__) +/** + * @brief Enables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVBAT(ADCDriver *adcp) { + + (void)adcp; + + ADC->CCR |= ADC_CCR_VBATEN; +} + +/** + * @brief Disables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVBAT(ADCDriver *adcp) { + + (void)adcp; + + ADC->CCR &= ~ADC_CCR_VBATEN; +} +#endif /* defined(ADC_CCR_VBATEN) */ + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h b/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h index 9f8a2aa3f9..c0263cc290 100644 --- a/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h +++ b/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h @@ -1,417 +1,417 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv1/hal_adc_lld.h - * @brief STM32 ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Sampling rates - * @{ - */ -#if defined(STM32F0XX) || defined(__DOXYGEN__) -#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */ -#define ADC_SMPR_SMP_7P5 1U /**< @brief 21 cycles conversion time. */ -#define ADC_SMPR_SMP_13P5 2U /**< @brief 28 cycles conversion time. */ -#define ADC_SMPR_SMP_28P5 3U /**< @brief 41 cycles conversion time. */ -#define ADC_SMPR_SMP_41P5 4U /**< @brief 54 cycles conversion time. */ -#define ADC_SMPR_SMP_55P5 5U /**< @brief 68 cycles conversion time. */ -#define ADC_SMPR_SMP_71P5 6U /**< @brief 84 cycles conversion time. */ -#define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */ -#elif defined(STM32L0XX) -#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */ -#define ADC_SMPR_SMP_3P5 1U /**< @brief 16 cycles conversion time. */ -#define ADC_SMPR_SMP_7P5 2U /**< @brief 20 cycles conversion time. */ -#define ADC_SMPR_SMP_12P5 3U /**< @brief 25 cycles conversion time. */ -#define ADC_SMPR_SMP_19P5 4U /**< @brief 31 cycles conversion time. */ -#define ADC_SMPR_SMP_39P5 5U /**< @brief 52 cycles conversion time. */ -#define ADC_SMPR_SMP_79P5 6U /**< @brief 92 cycles conversion time. */ -#define ADC_SMPR_SMP_160P5 7U /**< @brief 173 cycles conversion time. */ -#endif -/** @} */ - -/** - * @name CFGR1 register configuration helpers - * @{ - */ -#define ADC_CFGR1_RES_12BIT (0U << 3U) -#define ADC_CFGR1_RES_10BIT (1U << 3U) -#define ADC_CFGR1_RES_8BIT (2U << 3U) -#define ADC_CFGR1_RES_6BIT (3U << 3U) - -#define ADC_CFGR1_EXTSEL_MASK (15U << 6U) -#define ADC_CFGR1_EXTSEL_SRC(n) ((n) << 6U) - -#define ADC_CFGR1_EXTEN_MASK (3U << 10U) -#define ADC_CFGR1_EXTEN_DISABLED (0U << 10U) -#define ADC_CFGR1_EXTEN_RISING (1U << 10U) -#define ADC_CFGR1_EXTEN_FALLING (2U << 10U) -#define ADC_CFGR1_EXTEN_BOTH (3U << 10U) -/** @} */ - -/** - * @name CFGR2 register configuration helpers - * @{ - */ -#define STM32_ADC_CKMODE_MASK (3U << 30U) -#define STM32_ADC_CKMODE_ADCCLK (0U << 30U) -#define STM32_ADC_CKMODE_PCLK_DIV2 (1U << 30U) -#define STM32_ADC_CKMODE_PCLK_DIV4 (2U << 30U) -#define STM32_ADC_CKMODE_PCLK (3U << 30U) - -#if (STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) -#define ADC_CFGR2_OVSR_MASK (7U << 2U) -#define ADC_CFGR2_OVSR_2X (0U << 2U) -#define ADC_CFGR2_OVSR_4X (1U << 2U) -#define ADC_CFGR2_OVSR_8X (2U << 2U) -#define ADC_CFGR2_OVSR_16X (3U << 2U) -#define ADC_CFGR2_OVSR_32X (4U << 2U) -#define ADC_CFGR2_OVSR_64X (5U << 2U) -#define ADC_CFGR2_OVSR_128X (6U << 2U) -#define ADC_CFGR2_OVSR_256X (7U << 2U) - -#define ADC_CFGR2_OVSS_MASK (15 << 5U) -#define ADC_CFGR2_OVSS_SHIFT(n) ((n) << 5U) -#endif -/** @} */ - -/** - * @name Threashold register initializer - * @{ - */ -#define ADC_TR(low, high) (((uint32_t)(high) << 16U) | \ - (uint32_t)(low)) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC1 clock source selection. - */ -#if !defined(STM32_ADC_ADC1_CKMODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK -#endif - -/** - * @brief ADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_IRQ_PRIORITY 2 -#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 2 -#endif - -#if (STM32_ADC_SUPPORTS_PRESCALER == TRUE) || defined(__DOXYGEN__) -/* - * @brief ADC prescaler setting. - * @note This setting has effect only in asynchronous clock mode (the - * default, @p STM32_ADC_CKMODE_ADCCLK). - */ -#if !defined(STM32_ADC_PRESCALER_VALUE) || defined(__DOXYGEN__) -#define STM32_ADC_PRESCALER_VALUE 2 -#endif -#endif - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Supported devices checks.*/ -#if !defined(STM32F0XX) && !defined(STM32L0XX) -#error "ADCv1 only supports F0 and L0 STM32 devices" -#endif - -#if defined(STM32L0XX) || defined(__DOXYGEN__) -#define STM32_ADCV1_OVERSAMPLING TRUE -#else -#define STM32_ADCV1_OVERSAMPLING FALSE -#endif - -/* Registry checks.*/ -#if !defined(STM32_HAS_ADC1) -#error "STM32_HAS_ADC1 not defined in registry" -#endif - -#if !defined(STM32_ADC_SUPPORTS_PRESCALER) -#error "STM32_ADC_SUPPORTS_PRESCALER not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) -#error "STM32_ADC1_HANDLER not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) -#error "STM32_ADC1_NUMBER not defined in registry" -#endif - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -/* Units checks.*/ -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -/* At least one ADC must be assigned.*/ -#if !STM32_ADC_USE_ADC1 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -/* ADC IRQ priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -/* DMA IRQ priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -/* DMA priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM) -#error "ADC DMA stream not defined" -#endif -#if STM32_DMA_SUPPORTS_DMAMUX - -#else /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* Check on the validity of the assigned DMA channels.*/ -#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 - -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* ADC clock source checks.*/ -#if STM32_ADC_SUPPORTS_PRESCALER == TRUE -#if STM32_ADC_PRESCALER_VALUE == 1 -#define STM32_ADC_PRESC 0U -#elif STM32_ADC_PRESCALER_VALUE == 2 -#define STM32_ADC_PRESC 1U -#elif STM32_ADC_PRESCALER_VALUE == 4 -#define STM32_ADC_PRESC 2U -#elif STM32_ADC_PRESCALER_VALUE == 6 -#define STM32_ADC_PRESC 3U -#elif STM32_ADC_PRESCALER_VALUE == 8 -#define STM32_ADC_PRESC 4U -#elif STM32_ADC_PRESCALER_VALUE == 10 -#define STM32_ADC_PRESC 5U -#elif STM32_ADC_PRESCALER_VALUE == 12 -#define STM32_ADC_PRESC 6U -#elif STM32_ADC_PRESCALER_VALUE == 16 -#define STM32_ADC_PRESC 7U -#elif STM32_ADC_PRESCALER_VALUE == 32 -#define STM32_ADC_PRESC 8U -#elif STM32_ADC_PRESCALER_VALUE == 64 -#define STM32_ADC_PRESC 9U -#elif STM32_ADC_PRESCALER_VALUE == 128 -#define STM32_ADC_PRESC 10U -#elif STM32_ADC_PRESCALER_VALUE == 256 -#define STM32_ADC_PRESC 11U -#else -#error "Invalid value assigned to STM32_ADC_PRESCALER_VALUE" -#endif -#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. */ - ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */ -} adcerror_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#if (STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) -#define adc_lld_configuration_group_fields \ - /* ADC CFGR1 register initialization data. \ - NOTE: The bits DMAEN and DMACFG are enforced internally \ - to the driver, keep them to zero. \ - NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \ - specified in continuous more or if the buffer depth is \ - greater than one.*/ \ - uint32_t cfgr1; \ - /* ADC CFGR2 register initialization data. \ - NOTE: CKMODE bits must not be specified in this field and left to \ - zero.*/ \ - uint32_t cfgr2; \ - /* ADC TR register initialization data.*/ \ - uint32_t tr; \ - /* ADC SMPR register initialization data.*/ \ - uint32_t smpr; \ - /* ADC CHSELR register initialization data. \ - NOTE: The number of bits at logic level one in this register must \ - be equal to the number in the @p num_channels field.*/ \ - uint32_t chselr -#else -#define adc_lld_configuration_group_fields \ - /* ADC CFGR1 register initialization data. \ - NOTE: The bits DMAEN and DMACFG are enforced internally \ - to the driver, keep them to zero. \ - NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \ - specified in continuous more or if the buffer depth is \ - greater than one.*/ \ - uint32_t cfgr1; \ - /* ADC TR register initialization data.*/ \ - uint32_t tr; \ - /* ADC SMPR register initialization data.*/ \ - uint32_t smpr; \ - /* ADC CHSELR register initialization data. \ - NOTE: The number of bits at logic level one in this register must \ - be equal to the number in the @p num_channels field.*/ \ - uint32_t chselr -#endif - -/** - * @brief Changes the value of the ADC CCR register. - * @details Use this function in order to enable or disable the internal - * analog sources. See the documentation in the STM32 Reference - * Manual. - * @note PRESC bits must not be specified and left to zero. - */ -#define adcSTM32SetCCR(ccr) (ADC->CCR = (ccr)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); - void adc_lld_serve_interrupt(ADCDriver *adcp); - void adcSTM32EnableVREF(ADCDriver *adcp); - void adcSTM32DisableVREF(ADCDriver *adcp); - void adcSTM32EnableTS(ADCDriver *adcp); - void adcSTM32DisableTS(ADCDriver *adcp); -#if defined(ADC_CCR_VBATEN) - void adcSTM32EnableVBAT(ADCDriver *adcp); - void adcSTM32DisableVBAT(ADCDriver *adcp); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv1/hal_adc_lld.h + * @brief STM32 ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Sampling rates + * @{ + */ +#if defined(STM32F0XX) || defined(__DOXYGEN__) +#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */ +#define ADC_SMPR_SMP_7P5 1U /**< @brief 21 cycles conversion time. */ +#define ADC_SMPR_SMP_13P5 2U /**< @brief 28 cycles conversion time. */ +#define ADC_SMPR_SMP_28P5 3U /**< @brief 41 cycles conversion time. */ +#define ADC_SMPR_SMP_41P5 4U /**< @brief 54 cycles conversion time. */ +#define ADC_SMPR_SMP_55P5 5U /**< @brief 68 cycles conversion time. */ +#define ADC_SMPR_SMP_71P5 6U /**< @brief 84 cycles conversion time. */ +#define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */ +#elif defined(STM32L0XX) +#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */ +#define ADC_SMPR_SMP_3P5 1U /**< @brief 16 cycles conversion time. */ +#define ADC_SMPR_SMP_7P5 2U /**< @brief 20 cycles conversion time. */ +#define ADC_SMPR_SMP_12P5 3U /**< @brief 25 cycles conversion time. */ +#define ADC_SMPR_SMP_19P5 4U /**< @brief 31 cycles conversion time. */ +#define ADC_SMPR_SMP_39P5 5U /**< @brief 52 cycles conversion time. */ +#define ADC_SMPR_SMP_79P5 6U /**< @brief 92 cycles conversion time. */ +#define ADC_SMPR_SMP_160P5 7U /**< @brief 173 cycles conversion time. */ +#endif +/** @} */ + +/** + * @name CFGR1 register configuration helpers + * @{ + */ +#define ADC_CFGR1_RES_12BIT (0U << 3U) +#define ADC_CFGR1_RES_10BIT (1U << 3U) +#define ADC_CFGR1_RES_8BIT (2U << 3U) +#define ADC_CFGR1_RES_6BIT (3U << 3U) + +#define ADC_CFGR1_EXTSEL_MASK (15U << 6U) +#define ADC_CFGR1_EXTSEL_SRC(n) ((n) << 6U) + +#define ADC_CFGR1_EXTEN_MASK (3U << 10U) +#define ADC_CFGR1_EXTEN_DISABLED (0U << 10U) +#define ADC_CFGR1_EXTEN_RISING (1U << 10U) +#define ADC_CFGR1_EXTEN_FALLING (2U << 10U) +#define ADC_CFGR1_EXTEN_BOTH (3U << 10U) +/** @} */ + +/** + * @name CFGR2 register configuration helpers + * @{ + */ +#define STM32_ADC_CKMODE_MASK (3U << 30U) +#define STM32_ADC_CKMODE_ADCCLK (0U << 30U) +#define STM32_ADC_CKMODE_PCLK_DIV2 (1U << 30U) +#define STM32_ADC_CKMODE_PCLK_DIV4 (2U << 30U) +#define STM32_ADC_CKMODE_PCLK (3U << 30U) + +#if (STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) +#define ADC_CFGR2_OVSR_MASK (7U << 2U) +#define ADC_CFGR2_OVSR_2X (0U << 2U) +#define ADC_CFGR2_OVSR_4X (1U << 2U) +#define ADC_CFGR2_OVSR_8X (2U << 2U) +#define ADC_CFGR2_OVSR_16X (3U << 2U) +#define ADC_CFGR2_OVSR_32X (4U << 2U) +#define ADC_CFGR2_OVSR_64X (5U << 2U) +#define ADC_CFGR2_OVSR_128X (6U << 2U) +#define ADC_CFGR2_OVSR_256X (7U << 2U) + +#define ADC_CFGR2_OVSS_MASK (15 << 5U) +#define ADC_CFGR2_OVSS_SHIFT(n) ((n) << 5U) +#endif +/** @} */ + +/** + * @name Threashold register initializer + * @{ + */ +#define ADC_TR(low, high) (((uint32_t)(high) << 16U) | \ + (uint32_t)(low)) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC1 clock source selection. + */ +#if !defined(STM32_ADC_ADC1_CKMODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK +#endif + +/** + * @brief ADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_IRQ_PRIORITY 2 +#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 2 +#endif + +#if (STM32_ADC_SUPPORTS_PRESCALER == TRUE) || defined(__DOXYGEN__) +/* + * @brief ADC prescaler setting. + * @note This setting has effect only in asynchronous clock mode (the + * default, @p STM32_ADC_CKMODE_ADCCLK). + */ +#if !defined(STM32_ADC_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_ADC_PRESCALER_VALUE 2 +#endif +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Supported devices checks.*/ +#if !defined(STM32F0XX) && !defined(STM32L0XX) +#error "ADCv1 only supports F0 and L0 STM32 devices" +#endif + +#if defined(STM32L0XX) || defined(__DOXYGEN__) +#define STM32_ADCV1_OVERSAMPLING TRUE +#else +#define STM32_ADCV1_OVERSAMPLING FALSE +#endif + +/* Registry checks.*/ +#if !defined(STM32_HAS_ADC1) +#error "STM32_HAS_ADC1 not defined in registry" +#endif + +#if !defined(STM32_ADC_SUPPORTS_PRESCALER) +#error "STM32_ADC_SUPPORTS_PRESCALER not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) +#error "STM32_ADC1_HANDLER not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) +#error "STM32_ADC1_NUMBER not defined in registry" +#endif + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +/* Units checks.*/ +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +/* At least one ADC must be assigned.*/ +#if !STM32_ADC_USE_ADC1 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +/* ADC IRQ priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +/* DMA IRQ priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +/* DMA priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM) +#error "ADC DMA stream not defined" +#endif +#if STM32_DMA_SUPPORTS_DMAMUX + +#else /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* Check on the validity of the assigned DMA channels.*/ +#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 + +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* ADC clock source checks.*/ +#if STM32_ADC_SUPPORTS_PRESCALER == TRUE +#if STM32_ADC_PRESCALER_VALUE == 1 +#define STM32_ADC_PRESC 0U +#elif STM32_ADC_PRESCALER_VALUE == 2 +#define STM32_ADC_PRESC 1U +#elif STM32_ADC_PRESCALER_VALUE == 4 +#define STM32_ADC_PRESC 2U +#elif STM32_ADC_PRESCALER_VALUE == 6 +#define STM32_ADC_PRESC 3U +#elif STM32_ADC_PRESCALER_VALUE == 8 +#define STM32_ADC_PRESC 4U +#elif STM32_ADC_PRESCALER_VALUE == 10 +#define STM32_ADC_PRESC 5U +#elif STM32_ADC_PRESCALER_VALUE == 12 +#define STM32_ADC_PRESC 6U +#elif STM32_ADC_PRESCALER_VALUE == 16 +#define STM32_ADC_PRESC 7U +#elif STM32_ADC_PRESCALER_VALUE == 32 +#define STM32_ADC_PRESC 8U +#elif STM32_ADC_PRESCALER_VALUE == 64 +#define STM32_ADC_PRESC 9U +#elif STM32_ADC_PRESCALER_VALUE == 128 +#define STM32_ADC_PRESC 10U +#elif STM32_ADC_PRESCALER_VALUE == 256 +#define STM32_ADC_PRESC 11U +#else +#error "Invalid value assigned to STM32_ADC_PRESCALER_VALUE" +#endif +#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. */ + ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */ +} adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#if (STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) +#define adc_lld_configuration_group_fields \ + /* ADC CFGR1 register initialization data. \ + NOTE: The bits DMAEN and DMACFG are enforced internally \ + to the driver, keep them to zero. \ + NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \ + specified in continuous more or if the buffer depth is \ + greater than one.*/ \ + uint32_t cfgr1; \ + /* ADC CFGR2 register initialization data. \ + NOTE: CKMODE bits must not be specified in this field and left to \ + zero.*/ \ + uint32_t cfgr2; \ + /* ADC TR register initialization data.*/ \ + uint32_t tr; \ + /* ADC SMPR register initialization data.*/ \ + uint32_t smpr; \ + /* ADC CHSELR register initialization data. \ + NOTE: The number of bits at logic level one in this register must \ + be equal to the number in the @p num_channels field.*/ \ + uint32_t chselr +#else +#define adc_lld_configuration_group_fields \ + /* ADC CFGR1 register initialization data. \ + NOTE: The bits DMAEN and DMACFG are enforced internally \ + to the driver, keep them to zero. \ + NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \ + specified in continuous more or if the buffer depth is \ + greater than one.*/ \ + uint32_t cfgr1; \ + /* ADC TR register initialization data.*/ \ + uint32_t tr; \ + /* ADC SMPR register initialization data.*/ \ + uint32_t smpr; \ + /* ADC CHSELR register initialization data. \ + NOTE: The number of bits at logic level one in this register must \ + be equal to the number in the @p num_channels field.*/ \ + uint32_t chselr +#endif + +/** + * @brief Changes the value of the ADC CCR register. + * @details Use this function in order to enable or disable the internal + * analog sources. See the documentation in the STM32 Reference + * Manual. + * @note PRESC bits must not be specified and left to zero. + */ +#define adcSTM32SetCCR(ccr) (ADC->CCR = (ccr)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); + void adc_lld_serve_interrupt(ADCDriver *adcp); + void adcSTM32EnableVREF(ADCDriver *adcp); + void adcSTM32DisableVREF(ADCDriver *adcp); + void adcSTM32EnableTS(ADCDriver *adcp); + void adcSTM32DisableTS(ADCDriver *adcp); +#if defined(ADC_CCR_VBATEN) + void adcSTM32EnableVBAT(ADCDriver *adcp); + void adcSTM32DisableVBAT(ADCDriver *adcp); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv1/notes.txt b/os/hal/ports/STM32/LLD/ADCv1/notes.txt index 92241172a3..ec7103c3e5 100644 --- a/os/hal/ports/STM32/LLD/ADCv1/notes.txt +++ b/os/hal/ports/STM32/LLD/ADCv1/notes.txt @@ -1,16 +1,16 @@ -STM32 ADCv1 driver. - -Driver capability: - -- Supports the STM32 "simple" ADC, the one found on small devices (F0, L0). - -The file registry must export: - -STM32_HAS_ADC1 - ADC1 presence flag. -STM32_ADC_SUPPORTS_PRESCALER - Support of CCR PRESC field. -STM32_ADC_SUPPORTS_OVERSAMPLING - Support of oversampling-related fields. -STM32_ADC1_IRQ_SHARED_WITH_EXTI - TRUE if the IRQ is shared with EXTI. -STM32_ADC1_HANDLER - IRQ vector name. -STM32_ADC1_NUMBER - IRQ vector number. -STM32_ADC1_DMA_MSK - Mask of the compatible DMA channels. -STM32_ADC1_DMA_CHN - Mask of the channels mapping. +STM32 ADCv1 driver. + +Driver capability: + +- Supports the STM32 "simple" ADC, the one found on small devices (F0, L0). + +The file registry must export: + +STM32_HAS_ADC1 - ADC1 presence flag. +STM32_ADC_SUPPORTS_PRESCALER - Support of CCR PRESC field. +STM32_ADC_SUPPORTS_OVERSAMPLING - Support of oversampling-related fields. +STM32_ADC1_IRQ_SHARED_WITH_EXTI - TRUE if the IRQ is shared with EXTI. +STM32_ADC1_HANDLER - IRQ vector name. +STM32_ADC1_NUMBER - IRQ vector number. +STM32_ADC1_DMA_MSK - Mask of the compatible DMA channels. +STM32_ADC1_DMA_CHN - Mask of the channels mapping. diff --git a/os/hal/ports/STM32/LLD/ADCv2/driver.mk b/os/hal/ports/STM32/LLD/ADCv2/driver.mk index 9be6513bb1..c3fa0ada15 100644 --- a/os/hal/ports/STM32/LLD/ADCv2/driver.mk +++ b/os/hal/ports/STM32/LLD/ADCv2/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2 diff --git a/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c index 53a5439cd4..b7a57b9793 100644 --- a/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c +++ b/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c @@ -1,452 +1,452 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv2/hal_adc_lld.c - * @brief STM32 ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define ADC1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) - -#define ADC2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN) - -#define ADC3_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/** @brief ADC2 driver identifier.*/ -#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__) -ADCDriver ADCD2; -#endif - -/** @brief ADC3 driver identifier.*/ -#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) -ADCDriver ADCD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief ADC DMA service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \ - defined(__DOXYGEN__) -/** - * @brief ADC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC_HANDLER) { - uint32_t sr; - - OSAL_IRQ_PROLOGUE(); - -#if STM32_ADC_USE_ADC1 - sr = ADC1->SR; - ADC1->SR = 0; - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - if (ADCD1.grpp != NULL) - _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); - } - if (sr & ADC_SR_AWD) { - if (ADCD1.grpp != NULL) { - _adc_isr_error_code(&ADCD1, ADC_ERR_WATCHDOG); - } - } -#if defined(STM32_ADC_ADC1_IRQ_HOOK) - STM32_ADC_ADC1_IRQ_HOOK -#endif -#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); - } - if (sr & ADC_SR_AWD) { - if (ADCD2.grpp != NULL) { - _adc_isr_error_code(&ADCD2, ADC_ERR_WATCHDOG); - } - } -#if defined(STM32_ADC_ADC2_IRQ_HOOK) - STM32_ADC_ADC2_IRQ_HOOK -#endif -#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); - } - if (sr & ADC_SR_AWD) { - if (ADCD3.grpp != NULL) { - _adc_isr_error_code(&ADCD3, ADC_ERR_WATCHDOG); - } - } -#if defined(STM32_ADC_ADC3_IRQ_HOOK) - STM32_ADC_ADC3_IRQ_HOOK -#endif -#endif /* STM32_ADC_USE_ADC3 */ - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = NULL; - ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - -#if STM32_ADC_USE_ADC2 - /* Driver initialization.*/ - adcObjectInit(&ADCD2); - ADCD2.adc = ADC2; - ADCD2.dmastp = NULL; - ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - -#if STM32_ADC_USE_ADC3 - /* Driver initialization.*/ - adcObjectInit(&ADCD3); - ADCD3.adc = ADC3; - ADCD3.dmastp = NULL; - ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - - /* The shared vector is initialized on driver initialization and never - disabled because sharing.*/ - nvicEnableVector(STM32_ADC_NUMBER, 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) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - rccEnableADC1(true); - } -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC2 - if (&ADCD2 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM, - STM32_ADC_ADC2_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR); - rccEnableADC2(true); - } -#endif /* STM32_ADC_USE_ADC2 */ - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM, - STM32_ADC_ADC3_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR); - rccEnableADC3(true); - } -#endif /* STM32_ADC_USE_ADC3 */ - - /* This is a common register but apparently it requires that at least one - of the ADCs is clocked in order to allow writing, see bug 3575297.*/ - ADC->CCR = (ADC->CCR & (ADC_CCR_TSVREFE | ADC_CCR_VBATE)) | - (STM32_ADC_ADCPRE << 16); - - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - adcp->adc->CR2 = ADC_CR2_ADON; - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock.*/ - if (adcp->state == ADC_READY) { - - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC1(); -#endif - -#if STM32_ADC_USE_ADC2 - if (&ADCD2 == adcp) - rccDisableADC2(); -#endif - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) - rccDisableADC3(); -#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; - uint32_t cr2; - const ADCConversionGroup *grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup.*/ - adcp->adc->SR = 0; - adcp->adc->SMPR1 = grpp->smpr1; - adcp->adc->SMPR2 = grpp->smpr2; - adcp->adc->HTR = grpp->htr; - adcp->adc->LTR = grpp->ltr; - adcp->adc->SQR1 = grpp->sqr1 | ADC_SQR1_NUM_CH(grpp->num_channels); - adcp->adc->SQR2 = grpp->sqr2; - adcp->adc->SQR3 = grpp->sqr3; - - /* ADC configuration and start.*/ - adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; - - /* Enforcing the mandatory bits in CR2.*/ - cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; - - /* The start method is different dependign if HW or SW triggered, the - start is performed using the method specified in the CR2 configuration.*/ - if ((cr2 & ADC_CR2_SWSTART) != 0) { - /* Initializing CR2 while keeping ADC_CR2_SWSTART at zero.*/ - adcp->adc->CR2 = (cr2 | ADC_CR2_CONT) & ~ADC_CR2_SWSTART; - - /* Finally enabling ADC_CR2_SWSTART.*/ - adcp->adc->CR2 = (cr2 | ADC_CR2_CONT); - } - else - adcp->adc->CR2 = cr2; -} - -/** - * @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; - /* Because ticket #822, preserving injected conversions.*/ - adcp->adc->CR2 &= ~(ADC_CR2_SWSTART); - adcp->adc->CR2 = ADC_CR2_ADON; -} - -/** - * @brief Enables the TSVREFE bit. - * @details The TSVREFE bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - */ -void adcSTM32EnableTSVREFE(void) { - - ADC->CCR |= ADC_CCR_TSVREFE; -} - -/** - * @brief Disables the TSVREFE bit. - * @details The TSVREFE bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - */ -void adcSTM32DisableTSVREFE(void) { - - ADC->CCR &= ~ADC_CCR_TSVREFE; -} - -/** - * @brief Enables the VBATE bit. - * @details The VBATE bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - */ -void adcSTM32EnableVBATE(void) { - - ADC->CCR |= ADC_CCR_VBATE; -} - -/** - * @brief Disables the VBATE bit. - * @details The VBATE bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - */ -void adcSTM32DisableVBATE(void) { - - ADC->CCR &= ~ADC_CCR_VBATE; -} - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv2/hal_adc_lld.c + * @brief STM32 ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define ADC1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) + +#define ADC2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN) + +#define ADC3_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/** @brief ADC2 driver identifier.*/ +#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__) +ADCDriver ADCD2; +#endif + +/** @brief ADC3 driver identifier.*/ +#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) +ADCDriver ADCD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief ADC DMA service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \ + defined(__DOXYGEN__) +/** + * @brief ADC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC_HANDLER) { + uint32_t sr; + + OSAL_IRQ_PROLOGUE(); + +#if STM32_ADC_USE_ADC1 + sr = ADC1->SR; + ADC1->SR = 0; + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + if (ADCD1.grpp != NULL) + _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); + } + if (sr & ADC_SR_AWD) { + if (ADCD1.grpp != NULL) { + _adc_isr_error_code(&ADCD1, ADC_ERR_WATCHDOG); + } + } +#if defined(STM32_ADC_ADC1_IRQ_HOOK) + STM32_ADC_ADC1_IRQ_HOOK +#endif +#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); + } + if (sr & ADC_SR_AWD) { + if (ADCD2.grpp != NULL) { + _adc_isr_error_code(&ADCD2, ADC_ERR_WATCHDOG); + } + } +#if defined(STM32_ADC_ADC2_IRQ_HOOK) + STM32_ADC_ADC2_IRQ_HOOK +#endif +#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); + } + if (sr & ADC_SR_AWD) { + if (ADCD3.grpp != NULL) { + _adc_isr_error_code(&ADCD3, ADC_ERR_WATCHDOG); + } + } +#if defined(STM32_ADC_ADC3_IRQ_HOOK) + STM32_ADC_ADC3_IRQ_HOOK +#endif +#endif /* STM32_ADC_USE_ADC3 */ + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = NULL; + ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + +#if STM32_ADC_USE_ADC2 + /* Driver initialization.*/ + adcObjectInit(&ADCD2); + ADCD2.adc = ADC2; + ADCD2.dmastp = NULL; + ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + +#if STM32_ADC_USE_ADC3 + /* Driver initialization.*/ + adcObjectInit(&ADCD3); + ADCD3.adc = ADC3; + ADCD3.dmastp = NULL; + ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + + /* The shared vector is initialized on driver initialization and never + disabled because sharing.*/ + nvicEnableVector(STM32_ADC_NUMBER, 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) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + rccEnableADC1(true); + } +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM, + STM32_ADC_ADC2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR); + rccEnableADC2(true); + } +#endif /* STM32_ADC_USE_ADC2 */ + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM, + STM32_ADC_ADC3_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR); + rccEnableADC3(true); + } +#endif /* STM32_ADC_USE_ADC3 */ + + /* This is a common register but apparently it requires that at least one + of the ADCs is clocked in order to allow writing, see bug 3575297.*/ + ADC->CCR = (ADC->CCR & (ADC_CCR_TSVREFE | ADC_CCR_VBATE)) | + (STM32_ADC_ADCPRE << 16); + + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + adcp->adc->CR2 = ADC_CR2_ADON; + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock.*/ + if (adcp->state == ADC_READY) { + + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC1(); +#endif + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) + rccDisableADC2(); +#endif + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) + rccDisableADC3(); +#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; + uint32_t cr2; + const ADCConversionGroup *grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup.*/ + adcp->adc->SR = 0; + adcp->adc->SMPR1 = grpp->smpr1; + adcp->adc->SMPR2 = grpp->smpr2; + adcp->adc->HTR = grpp->htr; + adcp->adc->LTR = grpp->ltr; + adcp->adc->SQR1 = grpp->sqr1 | ADC_SQR1_NUM_CH(grpp->num_channels); + adcp->adc->SQR2 = grpp->sqr2; + adcp->adc->SQR3 = grpp->sqr3; + + /* ADC configuration and start.*/ + adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; + + /* Enforcing the mandatory bits in CR2.*/ + cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; + + /* The start method is different dependign if HW or SW triggered, the + start is performed using the method specified in the CR2 configuration.*/ + if ((cr2 & ADC_CR2_SWSTART) != 0) { + /* Initializing CR2 while keeping ADC_CR2_SWSTART at zero.*/ + adcp->adc->CR2 = (cr2 | ADC_CR2_CONT) & ~ADC_CR2_SWSTART; + + /* Finally enabling ADC_CR2_SWSTART.*/ + adcp->adc->CR2 = (cr2 | ADC_CR2_CONT); + } + else + adcp->adc->CR2 = cr2; +} + +/** + * @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; + /* Because ticket #822, preserving injected conversions.*/ + adcp->adc->CR2 &= ~(ADC_CR2_SWSTART); + adcp->adc->CR2 = ADC_CR2_ADON; +} + +/** + * @brief Enables the TSVREFE bit. + * @details The TSVREFE bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + */ +void adcSTM32EnableTSVREFE(void) { + + ADC->CCR |= ADC_CCR_TSVREFE; +} + +/** + * @brief Disables the TSVREFE bit. + * @details The TSVREFE bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + */ +void adcSTM32DisableTSVREFE(void) { + + ADC->CCR &= ~ADC_CCR_TSVREFE; +} + +/** + * @brief Enables the VBATE bit. + * @details The VBATE bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + */ +void adcSTM32EnableVBATE(void) { + + ADC->CCR |= ADC_CCR_VBATE; +} + +/** + * @brief Disables the VBATE bit. + * @details The VBATE bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + */ +void adcSTM32DisableVBATE(void) { + + ADC->CCR &= ~ADC_CCR_VBATE; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h b/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h index 5202f946b7..914a7ebbe7 100644 --- a/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h +++ b/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h @@ -1,486 +1,486 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv2/hal_adc_lld.h - * @brief STM32 ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Minimum ADC clock frequency. - */ -#define STM32_ADCCLK_MIN 600000 - -/** - * @brief Maximum ADC clock frequency. - */ -#if defined(STM32F4XX) || defined(__DOXYGEN__) -#define STM32_ADCCLK_MAX 36000000 -#else -#define STM32_ADCCLK_MAX 30000000 -#endif -/** @} */ - -/** - * @name Triggers selection - * @{ - */ -#define ADC_CR2_EXTEN_MASK (3U << 28U) -#define ADC_CR2_EXTEN_DISABLED (0U << 28U) -#define ADC_CR2_EXTEN_RISING (1U << 28U) -#define ADC_CR2_EXTEN_FALLING (2U << 28U) -#define ADC_CR2_EXTEN_BOTH (3U << 28U) - -#define ADC_CR2_EXTSEL_MASK (15U << 24U) -#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24U) -/** @} */ - -/** - * @name ADC clock divider settings - * @{ - */ -#define ADC_CCR_ADCPRE_DIV2 0 -#define ADC_CCR_ADCPRE_DIV4 1 -#define ADC_CCR_ADCPRE_DIV6 2 -#define ADC_CCR_ADCPRE_DIV8 3 -/** @} */ - -/** - * @name Available analog channels - * @{ - */ -#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ -#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ -#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ -#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ -#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ -#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ -#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ -#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ -#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ -#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ -#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ -#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ -#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ -#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ -#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ -#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ -#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor. - @note Available onADC1 only. */ -#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. - @note Available onADC1 only. */ -#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT. - @note Available onADC1 only. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */ -#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */ -#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */ -#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */ -#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */ -#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */ -#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */ -#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC common clock divider. - * @note This setting is influenced by the VDDA voltage and other - * external conditions, please refer to the datasheet for more - * info.
- * See section 5.3.20 "12-bit ADC characteristics". - */ -#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2 -#endif - -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC2 driver enable switch. - * @details If set to @p TRUE the support for ADC2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC2 FALSE -#endif - -/** - * @brief ADC3 driver enable switch. - * @details If set to @p TRUE the support for ADC3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC3 FALSE -#endif - -/** - * @brief DMA stream used for ADC1 operations. - */ -#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#endif - -/** - * @brief DMA stream used for ADC2 operations. - */ -#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#endif - -/** - * @brief DMA stream used for ADC3 operations. - */ -#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#endif - -/** - * @brief ADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC3 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - * @note This setting is shared among ADC1, ADC2 and ADC3 because - * all ADCs share the same vector. - */ -#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC1 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC2 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC3 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 -#endif - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2 -#error "ADC2 not present in the selected device" -#endif - -#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3 -#error "ADC3 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK) -#error "invalid DMA stream associated to ADC1" -#endif - -#if STM32_ADC_USE_ADC2 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK) -#error "invalid DMA stream associated to ADC2" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK) -#error "invalid DMA stream associated to ADC3" -#endif - -/* ADC clock related settings and checks.*/ -#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2 -#define STM32_ADCCLK (STM32_PCLK2 / 2) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4 -#define STM32_ADCCLK (STM32_PCLK2 / 4) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6 -#define STM32_ADCCLK (STM32_PCLK2 / 6) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8 -#define STM32_ADCCLK (STM32_PCLK2 / 8) -#else -#error "invalid STM32_ADC_ADCPRE value specified" -#endif - -#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX) -#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -typedef uint16_t adcsample_t; - -/** - * @brief Channels number in a conversion group. - */ -typedef uint16_t adc_channels_num_t; - -/** - * @brief Possible ADC failure causes. - * @note Error codes are architecture dependent and should not relied - * upon. - */ -typedef enum { - ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ - ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */ - ADC_ERR_WATCHDOG = 2 /**< ADC watchdog condition. */ -} adcerror_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_configuration_group_fields \ - /* 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; \ - /* 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; \ - /* ADC SMPR1 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 10...18.*/ \ - uint32_t smpr1; \ - /* ADC SMPR2 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 0...9.*/ \ - uint32_t smpr2; \ - /* ADC watchdog high threshold register. \ - NOTE: This field defines the high threshold of the analog watchdog.*/ \ - uint16_t htr; \ - /* ADC watchdog low threshold register. \ - NOTE: This field defines the low threshold of the analog watchdog.*/ \ - uint16_t ltr; \ - /* ADC SQR1 register initialization data. \ - NOTE: Conversion group sequence 13...16 + sequence length.*/ \ - uint32_t sqr1; \ - /* ADC SQR2 register initialization data. \ - NOTE: Conversion group sequence 7...12.*/ \ - uint32_t sqr2; \ - /* ADC SQR3 register initialization data. \ - NOTE: Conversion group sequence 1...6.*/ \ - uint32_t sqr3 - -/** - * @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. */ -/** @} */ - -/** - * @name Threshold settings helper macros - * @{ - */ -/** - * @brief High threshold limitation. - */ -#define ADC_HTR(n) ((n > ADC_HTR_HT) ? ADC_HTR_HT : n) -/** - * @brief Low threshold limitation. - */ -#define ADC_LTR(n) ((n > ADC_LTR_LT) ? ADC_LTR_LT : n) -/** @} */ - -/*===========================================================================*/ -/* 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 /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv2/hal_adc_lld.h + * @brief STM32 ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Minimum ADC clock frequency. + */ +#define STM32_ADCCLK_MIN 600000 + +/** + * @brief Maximum ADC clock frequency. + */ +#if defined(STM32F4XX) || defined(__DOXYGEN__) +#define STM32_ADCCLK_MAX 36000000 +#else +#define STM32_ADCCLK_MAX 30000000 +#endif +/** @} */ + +/** + * @name Triggers selection + * @{ + */ +#define ADC_CR2_EXTEN_MASK (3U << 28U) +#define ADC_CR2_EXTEN_DISABLED (0U << 28U) +#define ADC_CR2_EXTEN_RISING (1U << 28U) +#define ADC_CR2_EXTEN_FALLING (2U << 28U) +#define ADC_CR2_EXTEN_BOTH (3U << 28U) + +#define ADC_CR2_EXTSEL_MASK (15U << 24U) +#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24U) +/** @} */ + +/** + * @name ADC clock divider settings + * @{ + */ +#define ADC_CCR_ADCPRE_DIV2 0 +#define ADC_CCR_ADCPRE_DIV4 1 +#define ADC_CCR_ADCPRE_DIV6 2 +#define ADC_CCR_ADCPRE_DIV8 3 +/** @} */ + +/** + * @name Available analog channels + * @{ + */ +#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ +#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ +#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ +#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ +#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ +#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ +#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ +#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ +#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ +#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ +#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ +#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ +#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ +#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ +#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ +#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ +#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor. + @note Available onADC1 only. */ +#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. + @note Available onADC1 only. */ +#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT. + @note Available onADC1 only. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */ +#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */ +#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */ +#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */ +#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */ +#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */ +#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */ +#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC common clock divider. + * @note This setting is influenced by the VDDA voltage and other + * external conditions, please refer to the datasheet for more + * info.
+ * See section 5.3.20 "12-bit ADC characteristics". + */ +#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2 +#endif + +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC2 driver enable switch. + * @details If set to @p TRUE the support for ADC2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC2 FALSE +#endif + +/** + * @brief ADC3 driver enable switch. + * @details If set to @p TRUE the support for ADC3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC3 FALSE +#endif + +/** + * @brief DMA stream used for ADC1 operations. + */ +#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#endif + +/** + * @brief DMA stream used for ADC2 operations. + */ +#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#endif + +/** + * @brief DMA stream used for ADC3 operations. + */ +#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#endif + +/** + * @brief ADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC3 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + * @note This setting is shared among ADC1, ADC2 and ADC3 because + * all ADCs share the same vector. + */ +#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC1 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC2 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC3 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2 +#error "ADC2 not present in the selected device" +#endif + +#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3 +#error "ADC3 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK) +#error "invalid DMA stream associated to ADC1" +#endif + +#if STM32_ADC_USE_ADC2 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK) +#error "invalid DMA stream associated to ADC2" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK) +#error "invalid DMA stream associated to ADC3" +#endif + +/* ADC clock related settings and checks.*/ +#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2 +#define STM32_ADCCLK (STM32_PCLK2 / 2) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4 +#define STM32_ADCCLK (STM32_PCLK2 / 4) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6 +#define STM32_ADCCLK (STM32_PCLK2 / 6) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8 +#define STM32_ADCCLK (STM32_PCLK2 / 8) +#else +#error "invalid STM32_ADC_ADCPRE value specified" +#endif + +#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX) +#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +typedef uint16_t adcsample_t; + +/** + * @brief Channels number in a conversion group. + */ +typedef uint16_t adc_channels_num_t; + +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ + ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */ + ADC_ERR_WATCHDOG = 2 /**< ADC watchdog condition. */ +} adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_configuration_group_fields \ + /* 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; \ + /* 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; \ + /* ADC SMPR1 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 10...18.*/ \ + uint32_t smpr1; \ + /* ADC SMPR2 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 0...9.*/ \ + uint32_t smpr2; \ + /* ADC watchdog high threshold register. \ + NOTE: This field defines the high threshold of the analog watchdog.*/ \ + uint16_t htr; \ + /* ADC watchdog low threshold register. \ + NOTE: This field defines the low threshold of the analog watchdog.*/ \ + uint16_t ltr; \ + /* ADC SQR1 register initialization data. \ + NOTE: Conversion group sequence 13...16 + sequence length.*/ \ + uint32_t sqr1; \ + /* ADC SQR2 register initialization data. \ + NOTE: Conversion group sequence 7...12.*/ \ + uint32_t sqr2; \ + /* ADC SQR3 register initialization data. \ + NOTE: Conversion group sequence 1...6.*/ \ + uint32_t sqr3 + +/** + * @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. */ +/** @} */ + +/** + * @name Threshold settings helper macros + * @{ + */ +/** + * @brief High threshold limitation. + */ +#define ADC_HTR(n) ((n > ADC_HTR_HT) ? ADC_HTR_HT : n) +/** + * @brief Low threshold limitation. + */ +#define ADC_LTR(n) ((n > ADC_LTR_LT) ? ADC_LTR_LT : n) +/** @} */ + +/*===========================================================================*/ +/* 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 /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv2/notes.txt b/os/hal/ports/STM32/LLD/ADCv2/notes.txt index a13d3274de..4b79a3467c 100644 --- a/os/hal/ports/STM32/LLD/ADCv2/notes.txt +++ b/os/hal/ports/STM32/LLD/ADCv2/notes.txt @@ -1,13 +1,13 @@ -STM32 ADCv2 driver. - -Driver capability: - -- Supports the STM32 "advanced" ADC found on F2, F4 and F7 sub-families. - -The file registry must export: - -STM32_HAS_ADCx - ADCx presence flag (1..3). -STM32_ADC_HANDLER - IRQ vector name for ADCs (shared). -STM32_ADC_NUMBER - IRQ vector number for ADCs (shared). -STM32_ADCx_DMA_MSK - Mask of the compatible DMA channels. -STM32_ADCx_DMA_CHN - Mask of the channels mapping. +STM32 ADCv2 driver. + +Driver capability: + +- Supports the STM32 "advanced" ADC found on F2, F4 and F7 sub-families. + +The file registry must export: + +STM32_HAS_ADCx - ADCx presence flag (1..3). +STM32_ADC_HANDLER - IRQ vector name for ADCs (shared). +STM32_ADC_NUMBER - IRQ vector number for ADCs (shared). +STM32_ADCx_DMA_MSK - Mask of the compatible DMA channels. +STM32_ADCx_DMA_CHN - Mask of the channels mapping. diff --git a/os/hal/ports/STM32/LLD/ADCv3/driver.mk b/os/hal/ports/STM32/LLD/ADCv3/driver.mk index 049021c693..5812df4a24 100644 --- a/os/hal/ports/STM32/LLD/ADCv3/driver.mk +++ b/os/hal/ports/STM32/LLD/ADCv3/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3 diff --git a/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c index 7db9e694c4..5c5cfea1b0 100644 --- a/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c +++ b/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c @@ -1,1020 +1,1020 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv3/hal_adc_lld.c - * @brief STM32 ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define ADC1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) - -#define ADC2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN) - -#define ADC3_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN) - -#define ADC4_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC4_DMA_STREAM, STM32_ADC4_DMA_CHN) - -#if STM32_ADC_DUAL_MODE -#if STM32_ADC_COMPACT_SAMPLES -/* Compact type dual mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) -#define ADC_DMA_MDMA ADC_CCR_MDMA_HWORD - -#else /* !STM32_ADC_COMPACT_SAMPLES */ -/* Large type dual mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) -#define ADC_DMA_MDMA ADC_CCR_MDMA_WORD -#endif /* !STM32_ADC_COMPACT_SAMPLES */ - -#else /* !STM32_ADC_DUAL_MODE */ -#if STM32_ADC_COMPACT_SAMPLES -/* Compact type single mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) -#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED - -#else /* !STM32_ADC_COMPACT_SAMPLES */ -/* Large type single mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) -#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED -#endif /* !STM32_ADC_COMPACT_SAMPLES */ -#endif /* !STM32_ADC_DUAL_MODE */ - -/* Addressing header differences.*/ -#if !defined(ADC_IER_OVRIE) -#define ADC_IER_OVRIE ADC_IER_OVR -#endif - -#if !defined(ADC_IER_AWD1IE) -#define ADC_IER_AWD1IE ADC_IER_AWD1 -#endif - -#if !defined(ADC_ISR_ADRDY) -#define ADC_ISR_ADRDY ADC_ISR_ADRD -#endif - -/* The following bits are too different in the various headers, just - redefining those here. Values can be overridden by placing definitions - in hal_lld.h.*/ -#if !defined(STM32_ADC_CR_ADVREGEN) -#define STM32_ADC_CR_ADVREGEN (1U << 28) -#endif - -#if !defined(STM32_ADC_CR_DEEPPWD) -#define STM32_ADC_CR_DEEPPWD (1U << 29) -#endif - -/*===========================================================================*/ -/* 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 - -/** @brief ADC4 driver identifier.*/ -#if STM32_ADC_USE_ADC4 || defined(__DOXYGEN__) -ADCDriver ADCD4; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const ADCConfig default_config = { - .difsel = 0 -}; - -static uint32_t clkmask; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Enables the ADC voltage regulator. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_vreg_on(ADCDriver *adcp) { - - adcp->adcm->CR = 0; /* See RM.*/ - adcp->adcm->CR = STM32_ADC_CR_ADVREGEN; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR = STM32_ADC_CR_ADVREGEN; -#endif - osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); -} - -/** - * @brief Disables the ADC voltage regulator. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_vreg_off(ADCDriver *adcp) { - - adcp->adcm->CR = 0; /* See RM.*/ - adcp->adcm->CR = STM32_ADC_CR_DEEPPWD; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR = 0; - adcp->adcs->CR = STM32_ADC_CR_DEEPPWD; -#endif -} - -/** - * @brief Calibrates and ADC unit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_calibrate(ADCDriver *adcp) { - - osalDbgAssert(adcp->adcm->CR == STM32_ADC_CR_ADVREGEN, "invalid register state"); - - /* Differential calibration for master ADC.*/ - adcp->adcm->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF; - adcp->adcm->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF | ADC_CR_ADCAL; - while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0) - ; - - osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); - - /* Single-ended calibration for master ADC.*/ - adcp->adcm->CR = STM32_ADC_CR_ADVREGEN; - adcp->adcm->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCAL; - while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0) - ; - - osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); - -#if STM32_ADC_DUAL_MODE - osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN, "invalid register state"); - - /* Differential calibration for slave ADC.*/ - adcp->adcs->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF; - adcp->adcs->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF | ADC_CR_ADCAL; - while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0) - ; - - osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); - - /* Single-ended calibration for slave ADC.*/ - adcp->adcs->CR = STM32_ADC_CR_ADVREGEN; - adcp->adcs->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCAL; - while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0) - ; - - osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); -#endif -} - -/** - * @brief Enables the ADC analog circuit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_analog_on(ADCDriver *adcp) { - - adcp->adcm->CR |= ADC_CR_ADEN; - while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0) - ; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR |= ADC_CR_ADEN; - while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0) - ; -#endif -} - -/** - * @brief Disables the ADC analog circuit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_analog_off(ADCDriver *adcp) { - - adcp->adcm->CR |= ADC_CR_ADDIS; - while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0) - ; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR |= ADC_CR_ADDIS; - while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0) - ; -#endif -} - -/** - * @brief Stops an ongoing conversion, if any. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_stop_adc(ADCDriver *adcp) { - - if (adcp->adcm->CR & ADC_CR_ADSTART) { - adcp->adcm->CR |= ADC_CR_ADSTP; - while (adcp->adcm->CR & ADC_CR_ADSTP) - ; - adcp->adcm->IER = 0; - } -} - -/** - * @brief ADC DMA 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_dma_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} - -/** - * @brief ADC IRQ service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] isr content of the ISR register - */ -static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - /* 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 ((isr & ADC_ISR_OVR) && - (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); - } - if (isr & ADC_ISR_AWD1) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD1); - } - if (isr & ADC_ISR_AWD2) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD2); - } - if (isr & ADC_ISR_AWD3) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD3); - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || defined(__DOXYGEN__) -/** - * @brief ADC1/ADC2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - -#if STM32_ADC_DUAL_MODE - - isr = ADC1->ISR; - isr |= ADC2->ISR; - ADC1->ISR = isr; - ADC2->ISR = isr; -#if defined(STM32_ADC_ADC12_IRQ_HOOK) - STM32_ADC_ADC12_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD1, isr); - -#else /* !STM32_ADC_DUAL_MODE */ - -#if STM32_ADC_USE_ADC1 - isr = ADC1->ISR; - ADC1->ISR = isr; -#if defined(STM32_ADC_ADC1_IRQ_HOOK) - STM32_ADC_ADC1_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD1, isr); -#endif - -#if STM32_ADC_USE_ADC2 - isr = ADC2->ISR; - ADC2->ISR = isr; -#if defined(STM32_ADC_ADC2_IRQ_HOOK) - STM32_ADC_ADC2_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD2, isr); -#endif - -#endif /* !STM32_ADC_DUAL_MODE */ - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) -/** - * @brief ADC3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC3_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC3->ISR; - ADC3->ISR = isr; -#if defined(STM32_ADC_ADC3_IRQ_HOOK) - STM32_ADC_ADC3_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#if STM32_ADC_DUAL_MODE -/** - * @brief ADC4 interrupt handler (as ADC3 slave). - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC4_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC4->ISR; - ADC4->ISR = isr; - - adc_lld_serve_interrupt(&ADCD3, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_DUAL_MODE */ -#endif /* STM32_ADC_USE_ADC3 */ - -#if STM32_ADC_USE_ADC4 || defined(__DOXYGEN__) -/** - * @brief ADC4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC4_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC4->ISR; - ADC4->ISR = isr; - - adc_lld_serve_interrupt(&ADCD4, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_ADC4 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - - clkmask = 0; - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); -#if defined(ADC1_2_COMMON) - ADCD1.adcc = ADC1_2_COMMON; -#elif defined(ADC12_COMMON) - ADCD1.adcc = ADC12_COMMON; -#elif defined(ADC123_COMMON) - ADCD1.adcc = ADC123_COMMON; -#else - ADCD1.adcc = ADC1_COMMON; -#endif - ADCD1.adcm = ADC1; -#if STM32_ADC_DUAL_MODE - ADCD1.adcs = ADC2; -#endif - ADCD1.dmastp = NULL; - ADCD1.dmamode = ADC_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC2 - /* Driver initialization.*/ - adcObjectInit(&ADCD2); -#if defined(ADC1_2_COMMON) - ADCD2.adcc = ADC1_2_COMMON; -#elif defined(ADC12_COMMON) - ADCD2.adcc = ADC12_COMMON; -#elif defined(ADC123_COMMON) - ADCD2.adcc = ADC123_COMMON; -#endif - ADCD2.adcm = ADC2; - ADCD2.dmastp = NULL; - ADCD2.dmamode = ADC_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif /* STM32_ADC_USE_ADC2 */ - -#if STM32_ADC_USE_ADC3 - /* Driver initialization.*/ - adcObjectInit(&ADCD3); -#if defined(ADC3_4_COMMON) - ADCD3.adcc = ADC3_4_COMMON; -#elif defined(ADC345_COMMON) - ADCD3.adcc = ADC345_COMMON; -#elif defined(ADC123_COMMON) - ADCD3.adcc = ADC123_COMMON; -#else - ADCD3.adcc = ADC3_COMMON; -#endif - ADCD3.adcm = ADC3; -#if STM32_ADC_DUAL_MODE - ADCD3.adcs = ADC4; -#endif - ADCD3.dmastp = NULL; - ADCD3.dmamode = ADC_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif /* STM32_ADC_USE_ADC3 */ - -#if STM32_ADC_USE_ADC4 - /* Driver initialization.*/ - adcObjectInit(&ADCD4); -#if defined(ADC3_4_COMMON) - ADCD4.adcc = ADC3_4_COMMON; -#elif defined(ADC345_COMMON) - ADCD4.adcc = ADC345_COMMON; -#endif - ADCD4.adcm = ADC4; - ADCD4.dmastp = NULL; - ADCD4.dmamode = ADC_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif /* STM32_ADC_USE_ADC4 */ - - /* IRQs setup.*/ -#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 - nvicEnableVector(STM32_ADC1_NUMBER, STM32_ADC_ADC12_IRQ_PRIORITY); -#endif -#if STM32_ADC_USE_ADC3 - nvicEnableVector(STM32_ADC3_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY); -#if STM32_ADC_DUAL_MODE - nvicEnableVector(STM32_ADC4_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY); -#endif -#endif -#if STM32_ADC_USE_ADC4 - nvicEnableVector(STM32_ADC4_NUMBER, STM32_ADC_ADC4_IRQ_PRIORITY); -#endif - - /* ADC units pre-initializations.*/ -#if defined(STM32F3XX) -#if STM32_HAS_ADC1 && STM32_HAS_ADC2 -#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 - rccEnableADC12(true); - rccResetADC12(); - ADC1_2_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; - rccDisableADC12(); -#endif -#else -#if STM32_ADC_USE_ADC1 - rccEnableADC12(true); - rccResetADC12(); - ADC1_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; - rccDisableADC12(); -#endif -#endif -#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4 - rccEnableADC34(true); - rccResetADC34(); - ADC3_4_COMMON->CCR = STM32_ADC_ADC34_CLOCK_MODE | ADC_DMA_MDMA; - rccDisableADC34(); -#endif -#endif - -#if defined(STM32L4XX) || defined(STM32L4XXP) - rccEnableADC123(true); - rccResetADC123(); -#if defined(ADC1_2_COMMON) - ADC1_2_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; -#elif defined(ADC123_COMMON) - ADC123_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; -#else - ADC1_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; -#endif - - rccDisableADC123(); -#endif - -#if defined(STM32G4XX) -#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 - rccEnableADC12(true); - rccResetADC12(); - ADC12_COMMON->CCR = STM32_ADC_ADC12_PRESC | STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; - rccDisableADC12(); -#endif -#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4 - rccEnableADC345(true); - rccResetADC345(); - ADC345_COMMON->CCR = STM32_ADC_ADC345_PRESC | STM32_ADC_ADC345_CLOCK_MODE | ADC_DMA_MDMA; - rccDisableADC345(); -#endif -#endif -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - /* Handling the default configuration.*/ - if (adcp->config == NULL) { - adcp->config = &default_config; - } - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - clkmask |= (1 << 0); -#if defined(STM32F3XX) || defined(STM32G4XX) - rccEnableADC12(true); -#endif -#if defined(STM32L4XX) || defined(STM32L4XXP) - rccEnableADC123(true); -#endif -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1); -#endif - } -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC2 - if (&ADCD2 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM, - STM32_ADC_ADC2_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - clkmask |= (1 << 1); -#if defined(STM32F3XX) || defined(STM32G4XX) - rccEnableADC12(true); -#endif -#if defined(STM32L4XX) || defined(STM32L4XXP) - rccEnableADC123(true); -#endif -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC2); -#endif - } -#endif /* STM32_ADC_USE_ADC2 */ - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM, - STM32_ADC_ADC3_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - clkmask |= (1 << 2); -#if defined(STM32F3XX) - rccEnableADC34(true); -#endif -#if defined(STM32L4XX) || defined(STM32L4XXP) - rccEnableADC123(true); -#endif -#if defined(STM32G4XX) - rccEnableADC345(true); -#endif -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC3); -#endif - } -#endif /* STM32_ADC_USE_ADC3 */ - -#if STM32_ADC_USE_ADC4 - if (&ADCD4 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC4_DMA_STREAM, - STM32_ADC_ADC4_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - clkmask |= (1 << 3); -#if defined(STM32F3XX) - rccEnableADC34(true); -#endif -#if defined(STM32L4XX) || defined(STM32L4XXP) - rccEnableADC123(true); -#endif -#if defined(STM32G4XX) - rccEnableADC345(true); -#endif -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC4); -#endif - } -#endif /* STM32_ADC_USE_ADC4 */ - - /* Setting DMA peripheral-side pointer.*/ -#if STM32_ADC_DUAL_MODE - dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcc->CDR); -#else - dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcm->DR); -#endif - - /* Differential channels setting.*/ -#if STM32_ADC_DUAL_MODE - adcp->adcm->DIFSEL = adcp->config->difsel; - adcp->adcs->DIFSEL = adcp->config->difsel; -#else - adcp->adcm->DIFSEL = adcp->config->difsel; -#endif - - /* Master ADC calibration.*/ - adc_lld_vreg_on(adcp); - adc_lld_calibrate(adcp); - - /* Master ADC enabled here in order to reduce conversions latencies.*/ - adc_lld_analog_on(adcp); - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - - /* Releasing the associated DMA channel.*/ - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - - /* Stopping the ongoing conversion, if any.*/ - adc_lld_stop_adc(adcp); - - /* Disabling ADC analog circuit and regulator.*/ - adc_lld_analog_off(adcp); - adc_lld_vreg_off(adcp); - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - /* Resetting CCR options except default ones.*/ - clkmask &= ~(1 << 0); - } -#endif - -#if STM32_ADC_USE_ADC2 - if (&ADCD2 == adcp) { - clkmask &= ~(1 << 1); - } -#endif - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) { - clkmask &= ~(1 << 2); - } -#endif - -#if STM32_ADC_USE_ADC4 - if (&ADCD4 == adcp) { - clkmask &= ~(1 << 3); - } -#endif - -#if defined(STM32F3XX) -#if STM32_HAS_ADC1 || STM32_HAS_ADC2 - if ((clkmask & 0x3) == 0) { - rccDisableADC12(); - } -#endif - -#if STM32_HAS_ADC3 || STM32_HAS_ADC4 - if ((clkmask & 0xC) == 0) { - rccDisableADC34(); - } -#endif -#endif - -#if defined(STM32L4XX) || defined(STM32L4XXP) - if ((clkmask & 0x7) == 0) { - rccDisableADC123(); - } -#endif - -#if defined(STM32G4XX) -#if STM32_HAS_ADC1 || STM32_HAS_ADC2 - if ((clkmask & 0x3) == 0) { - rccDisableADC12(); - } -#endif - -#if STM32_HAS_ADC3 || STM32_HAS_ADC4 - if ((clkmask & 0xC) == 0) { - rccDisableADC345(); - } -#endif -#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 dmamode, cfgr; - const ADCConversionGroup *grpp = adcp->grpp; -#if STM32_ADC_DUAL_MODE - uint32_t ccr = grpp->ccr & ~(ADC_CCR_CKMODE_MASK | ADC_CCR_MDMA_MASK); -#endif - - osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0), - "odd number of channels in dual mode"); - - /* Calculating control registers values.*/ - dmamode = adcp->dmamode; - cfgr = grpp->cfgr | ADC_CFGR_DMAEN; - if (grpp->circular) { - dmamode |= STM32_DMA_CR_CIRC; -#if STM32_ADC_DUAL_MODE - ccr |= ADC_CCR_DMACFG_CIRCULAR; -#else - cfgr |= ADC_CFGR_DMACFG_CIRCULAR; -#endif - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - dmamode |= STM32_DMA_CR_HTIE; - } - } - - /* DMA setup.*/ - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); -#if STM32_ADC_DUAL_MODE - dmaStreamSetTransactionSize(adcp->dmastp, ((uint32_t)grpp->num_channels/2) * - (uint32_t)adcp->depth); -#else - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); -#endif - dmaStreamSetMode(adcp->dmastp, dmamode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup, if it is defined a callback for the analog watch dog then it - is enabled.*/ - adcp->adcm->ISR = adcp->adcm->ISR; - if (grpp->error_cb != NULL) { - adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE - | ADC_IER_AWD2IE - | ADC_IER_AWD3IE; - adcp->adcm->TR1 = grpp->tr1; - adcp->adcm->TR2 = grpp->tr2; - adcp->adcm->TR3 = grpp->tr3; - adcp->adcm->AWD2CR = grpp->awd2cr; - adcp->adcm->AWD3CR = grpp->awd3cr; - } - -#if STM32_ADC_DUAL_MODE - - /* Configuring the CCR register with the user-specified settings - in the conversion group configuration structure, static settings are - preserved.*/ - adcp->adcc->CCR = (adcp->adcc->CCR & - (ADC_CCR_CKMODE_MASK | ADC_CCR_MDMA_MASK)) | ccr; - - adcp->adcm->SMPR1 = grpp->smpr[0]; - adcp->adcm->SMPR2 = grpp->smpr[1]; - adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); - adcp->adcm->SQR2 = grpp->sqr[1]; - adcp->adcm->SQR3 = grpp->sqr[2]; - adcp->adcm->SQR4 = grpp->sqr[3]; - adcp->adcs->SMPR1 = grpp->ssmpr[0]; - adcp->adcs->SMPR2 = grpp->ssmpr[1]; - adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); - adcp->adcs->SQR2 = grpp->ssqr[1]; - adcp->adcs->SQR3 = grpp->ssqr[2]; - adcp->adcs->SQR4 = grpp->ssqr[3]; - -#else /* !STM32_ADC_DUAL_MODE */ - adcp->adcm->SMPR1 = grpp->smpr[0]; - adcp->adcm->SMPR2 = grpp->smpr[1]; - adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); - adcp->adcm->SQR2 = grpp->sqr[1]; - adcp->adcm->SQR3 = grpp->sqr[2]; - adcp->adcm->SQR4 = grpp->sqr[3]; -#endif /* !STM32_ADC_DUAL_MODE */ - - /* ADC configuration.*/ - adcp->adcm->CFGR = cfgr; -#if (STM32_ADCV3_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) - adcp->adcm->CFGR2 = grpp->cfgr2; -#endif - - /* Starting conversion.*/ - adcp->adcm->CR |= ADC_CR_ADSTART; -} - -/** - * @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); - adc_lld_stop_adc(adcp); -} - -/** - * @brief Enables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVREF(ADCDriver *adcp) { - - adcp->adcc->CCR |= ADC_CCR_VREFEN; -} - -/** - * @brief Disables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVREF(ADCDriver *adcp) { - - adcp->adcc->CCR &= ~ADC_CCR_VREFEN; -} - -/** - * @brief Enables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableTS(ADCDriver *adcp) { - - adcp->adcc->CCR |= ADC_CCR_TSEN; -} - -/** - * @brief Disables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableTS(ADCDriver *adcp) { - - adcp->adcc->CCR &= ~ADC_CCR_TSEN; -} - -/** - * @brief Enables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVBAT(ADCDriver *adcp) { - - adcp->adcc->CCR |= ADC_CCR_VBATEN; -} - -/** - * @brief Disables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVBAT(ADCDriver *adcp) { - - adcp->adcc->CCR &= ~ADC_CCR_VBATEN; -} - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv3/hal_adc_lld.c + * @brief STM32 ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define ADC1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) + +#define ADC2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN) + +#define ADC3_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN) + +#define ADC4_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC4_DMA_STREAM, STM32_ADC4_DMA_CHN) + +#if STM32_ADC_DUAL_MODE +#if STM32_ADC_COMPACT_SAMPLES +/* Compact type dual mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) +#define ADC_DMA_MDMA ADC_CCR_MDMA_HWORD + +#else /* !STM32_ADC_COMPACT_SAMPLES */ +/* Large type dual mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) +#define ADC_DMA_MDMA ADC_CCR_MDMA_WORD +#endif /* !STM32_ADC_COMPACT_SAMPLES */ + +#else /* !STM32_ADC_DUAL_MODE */ +#if STM32_ADC_COMPACT_SAMPLES +/* Compact type single mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) +#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED + +#else /* !STM32_ADC_COMPACT_SAMPLES */ +/* Large type single mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) +#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED +#endif /* !STM32_ADC_COMPACT_SAMPLES */ +#endif /* !STM32_ADC_DUAL_MODE */ + +/* Addressing header differences.*/ +#if !defined(ADC_IER_OVRIE) +#define ADC_IER_OVRIE ADC_IER_OVR +#endif + +#if !defined(ADC_IER_AWD1IE) +#define ADC_IER_AWD1IE ADC_IER_AWD1 +#endif + +#if !defined(ADC_ISR_ADRDY) +#define ADC_ISR_ADRDY ADC_ISR_ADRD +#endif + +/* The following bits are too different in the various headers, just + redefining those here. Values can be overridden by placing definitions + in hal_lld.h.*/ +#if !defined(STM32_ADC_CR_ADVREGEN) +#define STM32_ADC_CR_ADVREGEN (1U << 28) +#endif + +#if !defined(STM32_ADC_CR_DEEPPWD) +#define STM32_ADC_CR_DEEPPWD (1U << 29) +#endif + +/*===========================================================================*/ +/* 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 + +/** @brief ADC4 driver identifier.*/ +#if STM32_ADC_USE_ADC4 || defined(__DOXYGEN__) +ADCDriver ADCD4; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const ADCConfig default_config = { + .difsel = 0 +}; + +static uint32_t clkmask; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Enables the ADC voltage regulator. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_vreg_on(ADCDriver *adcp) { + + adcp->adcm->CR = 0; /* See RM.*/ + adcp->adcm->CR = STM32_ADC_CR_ADVREGEN; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR = STM32_ADC_CR_ADVREGEN; +#endif + osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); +} + +/** + * @brief Disables the ADC voltage regulator. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_vreg_off(ADCDriver *adcp) { + + adcp->adcm->CR = 0; /* See RM.*/ + adcp->adcm->CR = STM32_ADC_CR_DEEPPWD; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR = 0; + adcp->adcs->CR = STM32_ADC_CR_DEEPPWD; +#endif +} + +/** + * @brief Calibrates and ADC unit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_calibrate(ADCDriver *adcp) { + + osalDbgAssert(adcp->adcm->CR == STM32_ADC_CR_ADVREGEN, "invalid register state"); + + /* Differential calibration for master ADC.*/ + adcp->adcm->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF; + adcp->adcm->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF | ADC_CR_ADCAL; + while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0) + ; + + osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); + + /* Single-ended calibration for master ADC.*/ + adcp->adcm->CR = STM32_ADC_CR_ADVREGEN; + adcp->adcm->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCAL; + while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0) + ; + + osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); + +#if STM32_ADC_DUAL_MODE + osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN, "invalid register state"); + + /* Differential calibration for slave ADC.*/ + adcp->adcs->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF; + adcp->adcs->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCALDIF | ADC_CR_ADCAL; + while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0) + ; + + osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); + + /* Single-ended calibration for slave ADC.*/ + adcp->adcs->CR = STM32_ADC_CR_ADVREGEN; + adcp->adcs->CR = STM32_ADC_CR_ADVREGEN | ADC_CR_ADCAL; + while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0) + ; + + osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20)); +#endif +} + +/** + * @brief Enables the ADC analog circuit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_analog_on(ADCDriver *adcp) { + + adcp->adcm->CR |= ADC_CR_ADEN; + while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0) + ; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR |= ADC_CR_ADEN; + while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0) + ; +#endif +} + +/** + * @brief Disables the ADC analog circuit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_analog_off(ADCDriver *adcp) { + + adcp->adcm->CR |= ADC_CR_ADDIS; + while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0) + ; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR |= ADC_CR_ADDIS; + while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0) + ; +#endif +} + +/** + * @brief Stops an ongoing conversion, if any. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_stop_adc(ADCDriver *adcp) { + + if (adcp->adcm->CR & ADC_CR_ADSTART) { + adcp->adcm->CR |= ADC_CR_ADSTP; + while (adcp->adcm->CR & ADC_CR_ADSTP) + ; + adcp->adcm->IER = 0; + } +} + +/** + * @brief ADC DMA 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_dma_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} + +/** + * @brief ADC IRQ service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] isr content of the ISR register + */ +static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + /* 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 ((isr & ADC_ISR_OVR) && + (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); + } + if (isr & ADC_ISR_AWD1) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD1); + } + if (isr & ADC_ISR_AWD2) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD2); + } + if (isr & ADC_ISR_AWD3) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD3); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || defined(__DOXYGEN__) +/** + * @brief ADC1/ADC2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + +#if STM32_ADC_DUAL_MODE + + isr = ADC1->ISR; + isr |= ADC2->ISR; + ADC1->ISR = isr; + ADC2->ISR = isr; +#if defined(STM32_ADC_ADC12_IRQ_HOOK) + STM32_ADC_ADC12_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD1, isr); + +#else /* !STM32_ADC_DUAL_MODE */ + +#if STM32_ADC_USE_ADC1 + isr = ADC1->ISR; + ADC1->ISR = isr; +#if defined(STM32_ADC_ADC1_IRQ_HOOK) + STM32_ADC_ADC1_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD1, isr); +#endif + +#if STM32_ADC_USE_ADC2 + isr = ADC2->ISR; + ADC2->ISR = isr; +#if defined(STM32_ADC_ADC2_IRQ_HOOK) + STM32_ADC_ADC2_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD2, isr); +#endif + +#endif /* !STM32_ADC_DUAL_MODE */ + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) +/** + * @brief ADC3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC3_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC3->ISR; + ADC3->ISR = isr; +#if defined(STM32_ADC_ADC3_IRQ_HOOK) + STM32_ADC_ADC3_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#if STM32_ADC_DUAL_MODE +/** + * @brief ADC4 interrupt handler (as ADC3 slave). + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC4_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC4->ISR; + ADC4->ISR = isr; + + adc_lld_serve_interrupt(&ADCD3, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_DUAL_MODE */ +#endif /* STM32_ADC_USE_ADC3 */ + +#if STM32_ADC_USE_ADC4 || defined(__DOXYGEN__) +/** + * @brief ADC4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC4_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC4->ISR; + ADC4->ISR = isr; + + adc_lld_serve_interrupt(&ADCD4, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_ADC4 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + + clkmask = 0; + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); +#if defined(ADC1_2_COMMON) + ADCD1.adcc = ADC1_2_COMMON; +#elif defined(ADC12_COMMON) + ADCD1.adcc = ADC12_COMMON; +#elif defined(ADC123_COMMON) + ADCD1.adcc = ADC123_COMMON; +#else + ADCD1.adcc = ADC1_COMMON; +#endif + ADCD1.adcm = ADC1; +#if STM32_ADC_DUAL_MODE + ADCD1.adcs = ADC2; +#endif + ADCD1.dmastp = NULL; + ADCD1.dmamode = ADC_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC2 + /* Driver initialization.*/ + adcObjectInit(&ADCD2); +#if defined(ADC1_2_COMMON) + ADCD2.adcc = ADC1_2_COMMON; +#elif defined(ADC12_COMMON) + ADCD2.adcc = ADC12_COMMON; +#elif defined(ADC123_COMMON) + ADCD2.adcc = ADC123_COMMON; +#endif + ADCD2.adcm = ADC2; + ADCD2.dmastp = NULL; + ADCD2.dmamode = ADC_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif /* STM32_ADC_USE_ADC2 */ + +#if STM32_ADC_USE_ADC3 + /* Driver initialization.*/ + adcObjectInit(&ADCD3); +#if defined(ADC3_4_COMMON) + ADCD3.adcc = ADC3_4_COMMON; +#elif defined(ADC345_COMMON) + ADCD3.adcc = ADC345_COMMON; +#elif defined(ADC123_COMMON) + ADCD3.adcc = ADC123_COMMON; +#else + ADCD3.adcc = ADC3_COMMON; +#endif + ADCD3.adcm = ADC3; +#if STM32_ADC_DUAL_MODE + ADCD3.adcs = ADC4; +#endif + ADCD3.dmastp = NULL; + ADCD3.dmamode = ADC_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif /* STM32_ADC_USE_ADC3 */ + +#if STM32_ADC_USE_ADC4 + /* Driver initialization.*/ + adcObjectInit(&ADCD4); +#if defined(ADC3_4_COMMON) + ADCD4.adcc = ADC3_4_COMMON; +#elif defined(ADC345_COMMON) + ADCD4.adcc = ADC345_COMMON; +#endif + ADCD4.adcm = ADC4; + ADCD4.dmastp = NULL; + ADCD4.dmamode = ADC_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif /* STM32_ADC_USE_ADC4 */ + + /* IRQs setup.*/ +#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 + nvicEnableVector(STM32_ADC1_NUMBER, STM32_ADC_ADC12_IRQ_PRIORITY); +#endif +#if STM32_ADC_USE_ADC3 + nvicEnableVector(STM32_ADC3_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY); +#if STM32_ADC_DUAL_MODE + nvicEnableVector(STM32_ADC4_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY); +#endif +#endif +#if STM32_ADC_USE_ADC4 + nvicEnableVector(STM32_ADC4_NUMBER, STM32_ADC_ADC4_IRQ_PRIORITY); +#endif + + /* ADC units pre-initializations.*/ +#if defined(STM32F3XX) +#if STM32_HAS_ADC1 && STM32_HAS_ADC2 +#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 + rccEnableADC12(true); + rccResetADC12(); + ADC1_2_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; + rccDisableADC12(); +#endif +#else +#if STM32_ADC_USE_ADC1 + rccEnableADC12(true); + rccResetADC12(); + ADC1_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; + rccDisableADC12(); +#endif +#endif +#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4 + rccEnableADC34(true); + rccResetADC34(); + ADC3_4_COMMON->CCR = STM32_ADC_ADC34_CLOCK_MODE | ADC_DMA_MDMA; + rccDisableADC34(); +#endif +#endif + +#if defined(STM32L4XX) || defined(STM32L4XXP) + rccEnableADC123(true); + rccResetADC123(); +#if defined(ADC1_2_COMMON) + ADC1_2_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; +#elif defined(ADC123_COMMON) + ADC123_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; +#else + ADC1_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; +#endif + + rccDisableADC123(); +#endif + +#if defined(STM32G4XX) +#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 + rccEnableADC12(true); + rccResetADC12(); + ADC12_COMMON->CCR = STM32_ADC_ADC12_PRESC | STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; + rccDisableADC12(); +#endif +#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4 + rccEnableADC345(true); + rccResetADC345(); + ADC345_COMMON->CCR = STM32_ADC_ADC345_PRESC | STM32_ADC_ADC345_CLOCK_MODE | ADC_DMA_MDMA; + rccDisableADC345(); +#endif +#endif +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* Handling the default configuration.*/ + if (adcp->config == NULL) { + adcp->config = &default_config; + } + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + clkmask |= (1 << 0); +#if defined(STM32F3XX) || defined(STM32G4XX) + rccEnableADC12(true); +#endif +#if defined(STM32L4XX) || defined(STM32L4XXP) + rccEnableADC123(true); +#endif +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1); +#endif + } +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM, + STM32_ADC_ADC2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + clkmask |= (1 << 1); +#if defined(STM32F3XX) || defined(STM32G4XX) + rccEnableADC12(true); +#endif +#if defined(STM32L4XX) || defined(STM32L4XXP) + rccEnableADC123(true); +#endif +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC2); +#endif + } +#endif /* STM32_ADC_USE_ADC2 */ + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM, + STM32_ADC_ADC3_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + clkmask |= (1 << 2); +#if defined(STM32F3XX) + rccEnableADC34(true); +#endif +#if defined(STM32L4XX) || defined(STM32L4XXP) + rccEnableADC123(true); +#endif +#if defined(STM32G4XX) + rccEnableADC345(true); +#endif +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC3); +#endif + } +#endif /* STM32_ADC_USE_ADC3 */ + +#if STM32_ADC_USE_ADC4 + if (&ADCD4 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC4_DMA_STREAM, + STM32_ADC_ADC4_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + clkmask |= (1 << 3); +#if defined(STM32F3XX) + rccEnableADC34(true); +#endif +#if defined(STM32L4XX) || defined(STM32L4XXP) + rccEnableADC123(true); +#endif +#if defined(STM32G4XX) + rccEnableADC345(true); +#endif +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC4); +#endif + } +#endif /* STM32_ADC_USE_ADC4 */ + + /* Setting DMA peripheral-side pointer.*/ +#if STM32_ADC_DUAL_MODE + dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcc->CDR); +#else + dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcm->DR); +#endif + + /* Differential channels setting.*/ +#if STM32_ADC_DUAL_MODE + adcp->adcm->DIFSEL = adcp->config->difsel; + adcp->adcs->DIFSEL = adcp->config->difsel; +#else + adcp->adcm->DIFSEL = adcp->config->difsel; +#endif + + /* Master ADC calibration.*/ + adc_lld_vreg_on(adcp); + adc_lld_calibrate(adcp); + + /* Master ADC enabled here in order to reduce conversions latencies.*/ + adc_lld_analog_on(adcp); + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + + /* Releasing the associated DMA channel.*/ + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + + /* Stopping the ongoing conversion, if any.*/ + adc_lld_stop_adc(adcp); + + /* Disabling ADC analog circuit and regulator.*/ + adc_lld_analog_off(adcp); + adc_lld_vreg_off(adcp); + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + /* Resetting CCR options except default ones.*/ + clkmask &= ~(1 << 0); + } +#endif + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) { + clkmask &= ~(1 << 1); + } +#endif + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) { + clkmask &= ~(1 << 2); + } +#endif + +#if STM32_ADC_USE_ADC4 + if (&ADCD4 == adcp) { + clkmask &= ~(1 << 3); + } +#endif + +#if defined(STM32F3XX) +#if STM32_HAS_ADC1 || STM32_HAS_ADC2 + if ((clkmask & 0x3) == 0) { + rccDisableADC12(); + } +#endif + +#if STM32_HAS_ADC3 || STM32_HAS_ADC4 + if ((clkmask & 0xC) == 0) { + rccDisableADC34(); + } +#endif +#endif + +#if defined(STM32L4XX) || defined(STM32L4XXP) + if ((clkmask & 0x7) == 0) { + rccDisableADC123(); + } +#endif + +#if defined(STM32G4XX) +#if STM32_HAS_ADC1 || STM32_HAS_ADC2 + if ((clkmask & 0x3) == 0) { + rccDisableADC12(); + } +#endif + +#if STM32_HAS_ADC3 || STM32_HAS_ADC4 + if ((clkmask & 0xC) == 0) { + rccDisableADC345(); + } +#endif +#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 dmamode, cfgr; + const ADCConversionGroup *grpp = adcp->grpp; +#if STM32_ADC_DUAL_MODE + uint32_t ccr = grpp->ccr & ~(ADC_CCR_CKMODE_MASK | ADC_CCR_MDMA_MASK); +#endif + + osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0), + "odd number of channels in dual mode"); + + /* Calculating control registers values.*/ + dmamode = adcp->dmamode; + cfgr = grpp->cfgr | ADC_CFGR_DMAEN; + if (grpp->circular) { + dmamode |= STM32_DMA_CR_CIRC; +#if STM32_ADC_DUAL_MODE + ccr |= ADC_CCR_DMACFG_CIRCULAR; +#else + cfgr |= ADC_CFGR_DMACFG_CIRCULAR; +#endif + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + dmamode |= STM32_DMA_CR_HTIE; + } + } + + /* DMA setup.*/ + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); +#if STM32_ADC_DUAL_MODE + dmaStreamSetTransactionSize(adcp->dmastp, ((uint32_t)grpp->num_channels/2) * + (uint32_t)adcp->depth); +#else + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); +#endif + dmaStreamSetMode(adcp->dmastp, dmamode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup, if it is defined a callback for the analog watch dog then it + is enabled.*/ + adcp->adcm->ISR = adcp->adcm->ISR; + if (grpp->error_cb != NULL) { + adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE + | ADC_IER_AWD2IE + | ADC_IER_AWD3IE; + adcp->adcm->TR1 = grpp->tr1; + adcp->adcm->TR2 = grpp->tr2; + adcp->adcm->TR3 = grpp->tr3; + adcp->adcm->AWD2CR = grpp->awd2cr; + adcp->adcm->AWD3CR = grpp->awd3cr; + } + +#if STM32_ADC_DUAL_MODE + + /* Configuring the CCR register with the user-specified settings + in the conversion group configuration structure, static settings are + preserved.*/ + adcp->adcc->CCR = (adcp->adcc->CCR & + (ADC_CCR_CKMODE_MASK | ADC_CCR_MDMA_MASK)) | ccr; + + adcp->adcm->SMPR1 = grpp->smpr[0]; + adcp->adcm->SMPR2 = grpp->smpr[1]; + adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); + adcp->adcm->SQR2 = grpp->sqr[1]; + adcp->adcm->SQR3 = grpp->sqr[2]; + adcp->adcm->SQR4 = grpp->sqr[3]; + adcp->adcs->SMPR1 = grpp->ssmpr[0]; + adcp->adcs->SMPR2 = grpp->ssmpr[1]; + adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); + adcp->adcs->SQR2 = grpp->ssqr[1]; + adcp->adcs->SQR3 = grpp->ssqr[2]; + adcp->adcs->SQR4 = grpp->ssqr[3]; + +#else /* !STM32_ADC_DUAL_MODE */ + adcp->adcm->SMPR1 = grpp->smpr[0]; + adcp->adcm->SMPR2 = grpp->smpr[1]; + adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); + adcp->adcm->SQR2 = grpp->sqr[1]; + adcp->adcm->SQR3 = grpp->sqr[2]; + adcp->adcm->SQR4 = grpp->sqr[3]; +#endif /* !STM32_ADC_DUAL_MODE */ + + /* ADC configuration.*/ + adcp->adcm->CFGR = cfgr; +#if (STM32_ADCV3_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) + adcp->adcm->CFGR2 = grpp->cfgr2; +#endif + + /* Starting conversion.*/ + adcp->adcm->CR |= ADC_CR_ADSTART; +} + +/** + * @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); + adc_lld_stop_adc(adcp); +} + +/** + * @brief Enables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVREF(ADCDriver *adcp) { + + adcp->adcc->CCR |= ADC_CCR_VREFEN; +} + +/** + * @brief Disables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVREF(ADCDriver *adcp) { + + adcp->adcc->CCR &= ~ADC_CCR_VREFEN; +} + +/** + * @brief Enables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableTS(ADCDriver *adcp) { + + adcp->adcc->CCR |= ADC_CCR_TSEN; +} + +/** + * @brief Disables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableTS(ADCDriver *adcp) { + + adcp->adcc->CCR &= ~ADC_CCR_TSEN; +} + +/** + * @brief Enables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVBAT(ADCDriver *adcp) { + + adcp->adcc->CCR |= ADC_CCR_VBATEN; +} + +/** + * @brief Disables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVBAT(ADCDriver *adcp) { + + adcp->adcc->CCR &= ~ADC_CCR_VBATEN; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h b/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h index 8d6c6153d0..a42f9a3940 100644 --- a/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h +++ b/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h @@ -1,1026 +1,1026 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv3/hal_adc_lld.h - * @brief STM32 ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @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_IN16 16 /**< @brief External analog input 16. */ -#define ADC_CHANNEL_IN17 17 /**< @brief External analog input 17. */ -#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#if defined(STM32F3XX) || defined(__DOXYGEN__) -#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */ -#define ADC_SMPR_SMP_2P5 1 /**< @brief 15 cycles conversion time. */ -#define ADC_SMPR_SMP_4P5 2 /**< @brief 17 cycles conversion time. */ -#define ADC_SMPR_SMP_7P5 3 /**< @brief 20 cycles conversion time. */ -#define ADC_SMPR_SMP_19P5 4 /**< @brief 32 cycles conversion time. */ -#define ADC_SMPR_SMP_61P5 5 /**< @brief 74 cycles conversion time. */ -#define ADC_SMPR_SMP_181P5 6 /**< @brief 194 cycles conversion time. */ -#define ADC_SMPR_SMP_601P5 7 /**< @brief 614 cycles conversion time. */ -#endif -#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ADC_SMPR_SMP_2P5 0 /**< @brief 15 cycles conversion time */ -#define ADC_SMPR_SMP_6P5 1 /**< @brief 19 cycles conversion time. */ -#define ADC_SMPR_SMP_12P5 2 /**< @brief 25 cycles conversion time. */ -#define ADC_SMPR_SMP_24P5 3 /**< @brief 37 cycles conversion time. */ -#define ADC_SMPR_SMP_47P5 4 /**< @brief 60 cycles conversion time. */ -#define ADC_SMPR_SMP_92P5 5 /**< @brief 105 cycles conversion time. */ -#define ADC_SMPR_SMP_247P5 6 /**< @brief 260 cycles conversion time. */ -#define ADC_SMPR_SMP_640P5 7 /**< @brief 653 cycles conversion time. */ -#endif -/** @} */ - -/** - * @name CFGR register configuration helpers - * @{ - */ -#define ADC_CFGR_DMACFG_MASK (1 << 1) -#define ADC_CFGR_DMACFG_ONESHOT (0 << 1) -#define ADC_CFGR_DMACFG_CIRCULAR (1 << 1) - -#define ADC_CFGR_RES_MASK (3 << 3) -#define ADC_CFGR_RES_12BITS (0 << 3) -#define ADC_CFGR_RES_10BITS (1 << 3) -#define ADC_CFGR_RES_8BITS (2 << 3) -#define ADC_CFGR_RES_6BITS (3 << 3) - -#if defined(STM32F3XX) || defined(STM32L4XX) || defined(STM32L4XXP) || \ - defined(__DOXYGEN__) -#define ADC_CFGR_ALIGN_MASK (1 << 5) -#define ADC_CFGR_ALIGN_RIGHT (0 << 5) -#define ADC_CFGR_ALIGN_LEFT (1 << 5) - -#define ADC_CFGR_EXTSEL_MASK (15 << 6) -#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 6) -#endif -#if defined(STM32G4XX) -#define ADC_CFGR_ALIGN_MASK (1 << 15) -#define ADC_CFGR_ALIGN_RIGHT (0 << 15) -#define ADC_CFGR_ALIGN_LEFT (1 << 15) - -#define ADC_CFGR_EXTSEL_MASK (31 << 5) -#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 5) -#endif - -#define ADC_CFGR_EXTEN_MASK (3 << 10) -#define ADC_CFGR_EXTEN_DISABLED (0 << 10) -#define ADC_CFGR_EXTEN_RISING (1 << 10) -#define ADC_CFGR_EXTEN_FALLING (2 << 10) -#define ADC_CFGR_EXTEN_BOTH (3 << 10) - -#define ADC_CFGR_DISCEN_MASK (1 << 16) -#define ADC_CFGR_DISCEN_DISABLED (0 << 16) -#define ADC_CFGR_DISCEN_ENABLED (1 << 16) - -#define ADC_CFGR_DISCNUM_MASK (7 << 17) -#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17) - -#define ADC_CFGR_AWD1_DISABLED 0 -#define ADC_CFGR_AWD1_ALL (1 << 23) -#define ADC_CFGR_AWD1_SINGLE(n) (((n) << 26) | (1 << 23) | (1 << 22)) -/** @} */ - -/** - * @name CCR register configuration helpers - * @{ - */ -#define ADC_CCR_DUAL_MASK (31 << 0) -#define ADC_CCR_DUAL_FIELD(n) ((n) << 0) - -#define ADC_CCR_DELAY_MASK (15 << 8) -#define ADC_CCR_DELAY_FIELD(n) ((n) << 8) - -#define ADC_CCR_DMACFG_MASK (1 << 13) -#define ADC_CCR_DMACFG_ONESHOT (0 << 13) -#define ADC_CCR_DMACFG_CIRCULAR (1 << 13) - -#define ADC_CCR_MDMA_MASK (3 << 14) -#define ADC_CCR_MDMA_DISABLED (0 << 14) -#define ADC_CCR_MDMA_WORD (2 << 14) -#define ADC_CCR_MDMA_HWORD (3 << 14) - -#define ADC_CCR_CKMODE_MASK (3 << 16) -#define ADC_CCR_CKMODE_ADCCK (0 << 16) -#define ADC_CCR_CKMODE_AHB_DIV1 (1 << 16) -#define ADC_CCR_CKMODE_AHB_DIV2 (2 << 16) -#define ADC_CCR_CKMODE_AHB_DIV4 (3 << 16) - -#if !defined(STM32F3XX) -#define ADC_CCR_PRESC_MASK (15 << 18) -#define ADC_CCR_PRESC_NOCLOCK (0 << 18) -#define ADC_CCR_PRESC_DIV2 (1 << 18) -#define ADC_CCR_PRESC_DIV4 (2 << 18) -#define ADC_CCR_PRESC_DIV6 (3 << 18) -#define ADC_CCR_PRESC_DIV8 (4 << 18) -#define ADC_CCR_PRESC_DIV10 (5 << 18) -#define ADC_CCR_PRESC_DIV12 (6 << 18) -#define ADC_CCR_PRESC_DIV16 (7 << 18) -#define ADC_CCR_PRESC_DIV32 (8 << 18) -#define ADC_CCR_PRESC_DIV64 (9 << 18) -#define ADC_CCR_PRESC_DIV128 (10 << 18) -#define ADC_CCR_PRESC_DIV256 (11 << 18) -#endif /* !defined(STM32F3XX) */ - -/* F3 headers do not define the following macros, L4 headers do.*/ -#if !defined(ADC_CCR_VREFEN) || defined(__DOXYGEN__) -#define ADC_CCR_VREFEN (1 << 22) -#endif - -#if !defined(ADC_CCR_TSEN) || defined(__DOXYGEN__) -#define ADC_CCR_TSEN (1 << 23) -#endif - -#if !defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__) -#define ADC_CCR_VBATEN (1 << 24) -#endif -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Enables the ADC master/slave mode. - * @note In dual mode only ADCD1 and ADCD3 are available. - */ -#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_DUAL_MODE FALSE -#endif - -/** - * @brief Makes the ADC samples type an 8bits one. - * @note 10 and 12 bits sampling mode must not be used when this option - * is enabled. - */ -#if !defined(STM32_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__) -#define STM32_ADC_COMPACT_SAMPLES FALSE -#endif - -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC2 driver enable switch. - * @details If set to @p TRUE the support for ADC2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC2 FALSE -#endif - -/** - * @brief ADC3 driver enable switch. - * @details If set to @p TRUE the support for ADC3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC3 FALSE -#endif -/** - * @brief ADC4 driver enable switch. - * @details If set to @p TRUE the support for ADC4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC4) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC4 FALSE -#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 ADC4 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC4_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC1/ADC2 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC3 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC4 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC4_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 - -/** - * @brief ADC4 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC4_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 -#endif - -#if defined(STM32F3XX) || defined(__DOXYGEN__) -/** - * @brief ADC1/ADC2 clock source and mode. - */ -#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#endif - -/** - * @brief ADC3/ADC4 clock source and mode. - */ -#if !defined(STM32_ADC_ADC34_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#endif -#endif /* defined(STM32F3XX) */ - -#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(__DOXYGEN__) -/** - * @brief ADC1/ADC2/ADC3 clock source and mode. - */ -#if !defined(STM32_ADC_ADC123_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#endif - -/** - * @brief ADC1/ADC2/ADC3 clock prescaler. - */ -#if !defined(STM32_ADC_ADC123_PRESC) || defined(__DOXYGEN__) -#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 -#endif -#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */ - -#if defined(STM32G4XX) || defined(__DOXYGEN__) -/** - * @brief ADC1/ADC2 clock source and mode. - */ -#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#endif - -/** - * @brief ADC3/ADC4/ADC5 clock source and mode. - */ -#if !defined(STM32_ADC_ADC345_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC345_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#endif - -/** - * @brief ADC1/ADC2 clock prescaler. - */ -#if !defined(STM32_ADC_ADC12_PRESC) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2 -#endif - -/** - * @brief ADC3/ADC4/ADC5 clock prescaler. - */ -#if !defined(STM32_ADC_ADC345_PRESC) || defined(__DOXYGEN__) -#define STM32_ADC_ADC345_PRESC ADC_CCR_PRESC_DIV2 -#endif -#endif /* defined(STM32G4XX) */ - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Supported devices checks.*/ -#if !defined(STM32F3XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) && \ - !defined(STM32G4XX) -#error "ADCv3 only supports F3, L4, L4+ and G4 STM32 devices" -#endif - -#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) || \ - defined(__DOXYGEN__) -#define STM32_ADCV3_OVERSAMPLING TRUE -#else -#define STM32_ADCV3_OVERSAMPLING FALSE -#endif - -/* Registry checks.*/ -#if !defined(STM32_HAS_ADC1) || !defined(STM32_HAS_ADC2) || \ - !defined(STM32_HAS_ADC3) || !defined(STM32_HAS_ADC4) -#error "STM32_HAS_ADCx not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) || \ - (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_HANDLER)) || \ - (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_HANDLER)) || \ - (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_HANDLER)) -#error "STM32_ADCx_HANDLER not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) || \ - (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_NUMBER)) || \ - (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_NUMBER)) || \ - (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_NUMBER)) -#error "STM32_ADCx_NUMBER not defined in registry" -#endif - -#if !STM32_DMA_SUPPORTS_DMAMUX -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_DMA_MSK)) || \ - (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_DMA_MSK)) || \ - (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_DMA_MSK)) || \ - (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_DMA_MSK)) -#error "STM32_ADCx_DMA_MSK not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_DMA_CHN)) || \ - (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_DMA_CHN)) || \ - (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_DMA_CHN)) || \ - (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_DMA_CHN)) -#error "STM32_ADCx_DMA_CHN not defined in registry" -#endif -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* Units 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_ADC4 && !STM32_HAS_ADC4 -#error "ADC4 not present in the selected device" -#endif - -/* Units checks related to dual mode.*/ -#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC1 && !STM32_HAS_ADC2 -#error "ADC2 not present in the selected device, required for dual mode" -#endif - -#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC3 && !STM32_HAS_ADC4 -#error "ADC4 not present in the selected device, required for dual mode" -#endif - -#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC2 -#error "ADC2 cannot be used in dual mode" -#endif - -#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC4 -#error "ADC4 cannot be used in dual mode" -#endif - -/* At least one ADC must be assigned.*/ -#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && \ - !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -/* ISR arrangements checks.*/ -#if STM32_HAS_ADC1 && STM32_HAS_ADC2 -#if STM32_ADC1_NUMBER != STM32_ADC2_NUMBER -#error "ADCv3 driver expects STM32_ADC1_NUMBER == STM32_ADC2_NUMBER from registry" -#endif -#endif - -/* ADC IRQ priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC2" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC3" -#endif - -#if STM32_ADC_USE_ADC4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC4" -#endif - -/* DMA IRQ priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -#if STM32_ADC_USE_ADC2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC2 DMA" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC3 DMA" -#endif - -#if STM32_ADC_USE_ADC4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC4_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC4 DMA" -#endif - -/* DMA priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC2" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC3" -#endif - -#if STM32_ADC_USE_ADC4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC4" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM) -#error "ADC1 DMA stream not defined" -#endif - -#if STM32_ADC_USE_ADC2 && !defined(STM32_ADC_ADC2_DMA_STREAM) -#error "ADC2 DMA stream not defined" -#endif - -#if STM32_ADC_USE_ADC3 && !defined(STM32_ADC_ADC3_DMA_STREAM) -#error "ADC3 DMA stream not defined" -#endif - -#if STM32_ADC_USE_ADC4 && !defined(STM32_ADC_ADC4_DMA_STREAM) -#error "ADC4 DMA stream not defined" -#endif - -#if STM32_DMA_SUPPORTS_DMAMUX - -#else /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* Check on the validity of the assigned DMA channels.*/ -#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 - -#if STM32_ADC_USE_ADC4 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC4_DMA_STREAM, STM32_ADC4_DMA_MSK) -#error "invalid DMA stream associated to ADC4" -#endif - -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* ADC clock prescaler checks.*/ -#if defined(STM32F3XX) -#endif /* defined(STM32F3XX) */ - -#if defined(STM32L4XX) || defined(STM32L4XXP) -#if STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV2 -#define ADC123_PRESC_VALUE 2 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV4 -#define ADC123_PRESC_VALUE 4 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV6 -#define ADC123_PRESC_VALUE 6 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV8 -#define ADC123_PRESC_VALUE 8 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV10 -#define ADC123_PRESC_VALUE 10 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV12 -#define ADC123_PRESC_VALUE 12 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV16 -#define ADC123_PRESC_VALUE 16 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV32 -#define ADC123_PRESC_VALUE 32 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV64 -#define ADC123_PRESC_VALUE 64 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV128 -#define ADC123_PRESC_VALUE 128 -#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV256 -#define ADC123_PRESC_VALUE 256 -#error "invalid clock divider selected for STM32_ADC_ADC12_PRESC" -#endif -#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */ - -#if defined(STM32G4XX) -#if STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV2 -#define ADC12_PRESC_VALUE 2 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV4 -#define ADC12_PRESC_VALUE 4 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV6 -#define ADC12_PRESC_VALUE 6 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV8 -#define ADC12_PRESC_VALUE 8 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV10 -#define ADC12_PRESC_VALUE 10 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV12 -#define ADC12_PRESC_VALUE 12 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV16 -#define ADC12_PRESC_VALUE 16 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV32 -#define ADC12_PRESC_VALUE 32 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV64 -#define ADC12_PRESC_VALUE 64 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV128 -#define ADC12_PRESC_VALUE 128 -#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV256 -#define ADC12_PRESC_VALUE 256 -#error "invalid clock divider selected for STM32_ADC_ADC12_PRESC" -#endif - -#if STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV2 -#define ADC345_PRESC_VALUE 2 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV4 -#define ADC345_PRESC_VALUE 4 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV6 -#define ADC345_PRESC_VALUE 6 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV8 -#define ADC345_PRESC_VALUE 8 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV10 -#define ADC345_PRESC_VALUE 10 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV12 -#define ADC345_PRESC_VALUE 12 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV16 -#define ADC345_PRESC_VALUE 16 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV32 -#define ADC345_PRESC_VALUE 32 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV64 -#define ADC345_PRESC_VALUE 64 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV128 -#define ADC345_PRESC_VALUE 128 -#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV256 -#define ADC345_PRESC_VALUE 256 -#error "invalid clock divider selected for STM32_ADC_ADC345_PRESC" -#endif -#endif /* defined(STM32G4XX) */ - -/* ADC clock source checks.*/ -#if defined(STM32F3XX) -#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC12_CLOCK STM32_ADC12CLK -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC12_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC12_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC12_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" -#endif - -#if STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC34_CLOCK STM32_ADC34CLK -#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC34_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC34_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC34_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC34_CLOCK_MODE" -#endif - -#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -#if STM32_ADC34_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC34_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif -#endif /* defined(STM32F3XX) */ - -#if defined(STM32L4XX) || defined(STM32L4XXP) -#if STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC123_CLOCK (STM32_ADCCLK / ADC123_PRESC_VALUE) -#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC123_CLOCK (STM32_ADCCLK / 1) -#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC123_CLOCK (STM32_ADCCLK / 2) -#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC123_CLOCK (STM32_ADCCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC123_CLOCK_MODE" -#endif - -#if STM32_ADC123_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC123_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif -#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */ - -#if defined(STM32G4XX) -#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC12_CLOCK (STM32_ADC12CLK / ADC12_PRESC_VALUE) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC12_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC12_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC12_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" -#endif - -#if STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC345_CLOCK (STM32_ADC345CLK / ADC345_PRESC_VALUE) -#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC345_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC345_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC345_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC345_CLOCK_MODE" -#endif - -#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -#if STM32_ADC345_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC345_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif -#endif /* defined(STM32G4XX) */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -#if !STM32_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__) -typedef uint16_t adcsample_t; -#else -typedef uint8_t adcsample_t; -#endif - -/** - * @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. */ - ADC_ERR_AWD1 = 2, /**< Watchdog 1 triggered. */ - ADC_ERR_AWD2 = 3, /**< Watchdog 2 triggered. */ - ADC_ERR_AWD3 = 4 /**< Watchdog 3 triggered. */ -} adcerror_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) -#define adc_lld_driver_fields \ - /* Pointer to the master ADCx registers block.*/ \ - ADC_TypeDef *adcm; \ - /* Pointer to the slave ADCx registers block.*/ \ - ADC_TypeDef *adcs; \ - /* Pointer to the common ADCx_y registers block.*/ \ - ADC_Common_TypeDef *adcc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode -#else -#define adc_lld_driver_fields \ - /* Pointer to the master ADCx registers block.*/ \ - ADC_TypeDef *adcm; \ - /* Pointer to the slave ADCx registers block.*/ \ - ADC_Common_TypeDef *adcc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode -#endif - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* ADC DIFSEL register initialization data.*/ \ - uint32_t difsel - -/** - * @brief Low level fields of the ADC group configuration structure. - */ -#if (STM32_ADCV3_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) -#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) -#define adc_lld_configuration_group_fields \ - /* ADC CFGR register initialization data. \ - NOTE: The bits DMAEN and DMACFG are enforced internally \ - to the driver, keep them to zero. \ - NOTE: The bits @p ADC_CFGR_CONT or @p ADC_CFGR_DISCEN must be \ - specified in continuous mode or if the buffer depth is \ - greater than one.*/ \ - uint32_t cfgr; \ - /* ADC CFGR2 register initialization data.*/ \ - uint32_t cfgr2; \ - /* ADC TR1 register initialization data.*/ \ - uint32_t tr1; \ - /* ADC TR2 register initialization data.*/ \ - uint32_t tr2; \ - /* ADC TR3 register initialization data.*/ \ - uint32_t tr3; \ - /* ADC AWD2CR register initialization data.*/ \ - uint32_t awd2cr; \ - /* ADC AWD3CR register initialization data.*/ \ - uint32_t awd3cr; \ - /* ADC CCR register initialization data. \ - NOTE: Put this field to zero if not using oversampling.*/ \ - uint32_t ccr; \ - /* ADC SMPRx registers initialization data.*/ \ - uint32_t smpr[2]; \ - /* ADC SQRx register initialization data.*/ \ - uint32_t sqr[4]; \ - /* Slave ADC SMPRx registers initialization data. \ - NOTE: This field is only present in dual mode.*/ \ - uint32_t ssmpr[2]; \ - /* Slave ADC SQRx register initialization data. \ - NOTE: This field is only present in dual mode.*/ \ - uint32_t ssqr[4] -#else /* STM32_ADC_DUAL_MODE == FALSE */ -#define adc_lld_configuration_group_fields \ - uint32_t cfgr; \ - uint32_t cfgr2; \ - uint32_t tr1; \ - uint32_t tr2; \ - uint32_t tr3; \ - uint32_t awd2cr; \ - uint32_t awd3cr; \ - uint32_t smpr[2]; \ - uint32_t sqr[4] -#endif /* STM32_ADC_DUAL_MODE == FALSE */ - -#else /* STM32_ADCV3_OVERSAMPLING == FALSE */ -#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) -#define adc_lld_configuration_group_fields \ - uint32_t cfgr; \ - uint32_t tr1; \ - uint32_t tr2; \ - uint32_t tr3; \ - uint32_t awd2cr; \ - uint32_t awd3cr; \ - uint32_t ccr; \ - uint32_t smpr[2]; \ - uint32_t sqr[4]; \ - uint32_t ssmpr[2]; \ - uint32_t ssqr[4] -#else /* STM32_ADC_DUAL_MODE == FALSE */ -#define adc_lld_configuration_group_fields \ - uint32_t cfgr; \ - uint32_t tr1; \ - uint32_t tr2; \ - uint32_t tr3; \ - uint32_t awd2cr; \ - uint32_t awd3cr; \ - uint32_t smpr[2]; \ - uint32_t sqr[4] -#endif /* STM32_ADC_DUAL_MODE == FALSE */ -#endif /* STM32_ADCV3_OVERSAMPLING == FALSE */ - -/** - * @name Threshold registers initializers - * @{ - */ -#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low)) -#define ADC_TR_DISABLED ADC_TR(0U, 0x0FFFU) -#define ADC_AWDCR_ENABLE(n) (1U << (n)) -/** @} */ - -/** - * @name Sequences building helper macros - * @{ - */ -/** - * @brief Number of channels in a conversion sequence. - */ -#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 0) - -#define ADC_SQR1_SQ1_N(n) ((n) << 6) /**< @brief 1st channel in seq. */ -#define ADC_SQR1_SQ2_N(n) ((n) << 12) /**< @brief 2nd channel in seq. */ -#define ADC_SQR1_SQ3_N(n) ((n) << 18) /**< @brief 3rd channel in seq. */ -#define ADC_SQR1_SQ4_N(n) ((n) << 24) /**< @brief 4th channel in seq. */ - -#define ADC_SQR2_SQ5_N(n) ((n) << 0) /**< @brief 5th channel in seq. */ -#define ADC_SQR2_SQ6_N(n) ((n) << 6) /**< @brief 6th channel in seq. */ -#define ADC_SQR2_SQ7_N(n) ((n) << 12) /**< @brief 7th channel in seq. */ -#define ADC_SQR2_SQ8_N(n) ((n) << 18) /**< @brief 8th channel in seq. */ -#define ADC_SQR2_SQ9_N(n) ((n) << 24) /**< @brief 9th channel in seq. */ - -#define ADC_SQR3_SQ10_N(n) ((n) << 0) /**< @brief 10th channel in seq.*/ -#define ADC_SQR3_SQ11_N(n) ((n) << 6) /**< @brief 11th channel in seq.*/ -#define ADC_SQR3_SQ12_N(n) ((n) << 12) /**< @brief 12th channel in seq.*/ -#define ADC_SQR3_SQ13_N(n) ((n) << 18) /**< @brief 13th channel in seq.*/ -#define ADC_SQR3_SQ14_N(n) ((n) << 24) /**< @brief 14th channel in seq.*/ - -#define ADC_SQR4_SQ15_N(n) ((n) << 0) /**< @brief 15th channel in seq.*/ -#define ADC_SQR4_SQ16_N(n) ((n) << 6) /**< @brief 16th channel in seq.*/ -/** @} */ - -/** - * @name Sampling rate settings helper macros - * @{ - */ -#define ADC_SMPR1_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */ -#define ADC_SMPR1_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ -#define ADC_SMPR1_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ -#define ADC_SMPR1_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ -#define ADC_SMPR1_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ -#define ADC_SMPR1_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ -#define ADC_SMPR1_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ -#define ADC_SMPR1_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ -#define ADC_SMPR1_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ -#define ADC_SMPR1_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ - -#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ -#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ -#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ -#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ -#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ -#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ -#define ADC_SMPR2_SMP_AN16(n) ((n) << 18) /**< @brief AN16 sampling time. */ -#define ADC_SMPR2_SMP_AN17(n) ((n) << 21) /**< @brief AN17 sampling time. */ -#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 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 - -#if STM32_ADC_USE_ADC4 && !defined(__DOXYGEN__) -extern ADCDriver ADCD4; -#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 adcSTM32EnableVREF(ADCDriver *adcp); - void adcSTM32DisableVREF(ADCDriver *adcp); - void adcSTM32EnableTS(ADCDriver *adcp); - void adcSTM32DisableTS(ADCDriver *adcp); - void adcSTM32EnableVBAT(ADCDriver *adcp); - void adcSTM32DisableVBAT(ADCDriver *adcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv3/hal_adc_lld.h + * @brief STM32 ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @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_IN16 16 /**< @brief External analog input 16. */ +#define ADC_CHANNEL_IN17 17 /**< @brief External analog input 17. */ +#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#if defined(STM32F3XX) || defined(__DOXYGEN__) +#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */ +#define ADC_SMPR_SMP_2P5 1 /**< @brief 15 cycles conversion time. */ +#define ADC_SMPR_SMP_4P5 2 /**< @brief 17 cycles conversion time. */ +#define ADC_SMPR_SMP_7P5 3 /**< @brief 20 cycles conversion time. */ +#define ADC_SMPR_SMP_19P5 4 /**< @brief 32 cycles conversion time. */ +#define ADC_SMPR_SMP_61P5 5 /**< @brief 74 cycles conversion time. */ +#define ADC_SMPR_SMP_181P5 6 /**< @brief 194 cycles conversion time. */ +#define ADC_SMPR_SMP_601P5 7 /**< @brief 614 cycles conversion time. */ +#endif +#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ADC_SMPR_SMP_2P5 0 /**< @brief 15 cycles conversion time */ +#define ADC_SMPR_SMP_6P5 1 /**< @brief 19 cycles conversion time. */ +#define ADC_SMPR_SMP_12P5 2 /**< @brief 25 cycles conversion time. */ +#define ADC_SMPR_SMP_24P5 3 /**< @brief 37 cycles conversion time. */ +#define ADC_SMPR_SMP_47P5 4 /**< @brief 60 cycles conversion time. */ +#define ADC_SMPR_SMP_92P5 5 /**< @brief 105 cycles conversion time. */ +#define ADC_SMPR_SMP_247P5 6 /**< @brief 260 cycles conversion time. */ +#define ADC_SMPR_SMP_640P5 7 /**< @brief 653 cycles conversion time. */ +#endif +/** @} */ + +/** + * @name CFGR register configuration helpers + * @{ + */ +#define ADC_CFGR_DMACFG_MASK (1 << 1) +#define ADC_CFGR_DMACFG_ONESHOT (0 << 1) +#define ADC_CFGR_DMACFG_CIRCULAR (1 << 1) + +#define ADC_CFGR_RES_MASK (3 << 3) +#define ADC_CFGR_RES_12BITS (0 << 3) +#define ADC_CFGR_RES_10BITS (1 << 3) +#define ADC_CFGR_RES_8BITS (2 << 3) +#define ADC_CFGR_RES_6BITS (3 << 3) + +#if defined(STM32F3XX) || defined(STM32L4XX) || defined(STM32L4XXP) || \ + defined(__DOXYGEN__) +#define ADC_CFGR_ALIGN_MASK (1 << 5) +#define ADC_CFGR_ALIGN_RIGHT (0 << 5) +#define ADC_CFGR_ALIGN_LEFT (1 << 5) + +#define ADC_CFGR_EXTSEL_MASK (15 << 6) +#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 6) +#endif +#if defined(STM32G4XX) +#define ADC_CFGR_ALIGN_MASK (1 << 15) +#define ADC_CFGR_ALIGN_RIGHT (0 << 15) +#define ADC_CFGR_ALIGN_LEFT (1 << 15) + +#define ADC_CFGR_EXTSEL_MASK (31 << 5) +#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 5) +#endif + +#define ADC_CFGR_EXTEN_MASK (3 << 10) +#define ADC_CFGR_EXTEN_DISABLED (0 << 10) +#define ADC_CFGR_EXTEN_RISING (1 << 10) +#define ADC_CFGR_EXTEN_FALLING (2 << 10) +#define ADC_CFGR_EXTEN_BOTH (3 << 10) + +#define ADC_CFGR_DISCEN_MASK (1 << 16) +#define ADC_CFGR_DISCEN_DISABLED (0 << 16) +#define ADC_CFGR_DISCEN_ENABLED (1 << 16) + +#define ADC_CFGR_DISCNUM_MASK (7 << 17) +#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17) + +#define ADC_CFGR_AWD1_DISABLED 0 +#define ADC_CFGR_AWD1_ALL (1 << 23) +#define ADC_CFGR_AWD1_SINGLE(n) (((n) << 26) | (1 << 23) | (1 << 22)) +/** @} */ + +/** + * @name CCR register configuration helpers + * @{ + */ +#define ADC_CCR_DUAL_MASK (31 << 0) +#define ADC_CCR_DUAL_FIELD(n) ((n) << 0) + +#define ADC_CCR_DELAY_MASK (15 << 8) +#define ADC_CCR_DELAY_FIELD(n) ((n) << 8) + +#define ADC_CCR_DMACFG_MASK (1 << 13) +#define ADC_CCR_DMACFG_ONESHOT (0 << 13) +#define ADC_CCR_DMACFG_CIRCULAR (1 << 13) + +#define ADC_CCR_MDMA_MASK (3 << 14) +#define ADC_CCR_MDMA_DISABLED (0 << 14) +#define ADC_CCR_MDMA_WORD (2 << 14) +#define ADC_CCR_MDMA_HWORD (3 << 14) + +#define ADC_CCR_CKMODE_MASK (3 << 16) +#define ADC_CCR_CKMODE_ADCCK (0 << 16) +#define ADC_CCR_CKMODE_AHB_DIV1 (1 << 16) +#define ADC_CCR_CKMODE_AHB_DIV2 (2 << 16) +#define ADC_CCR_CKMODE_AHB_DIV4 (3 << 16) + +#if !defined(STM32F3XX) +#define ADC_CCR_PRESC_MASK (15 << 18) +#define ADC_CCR_PRESC_NOCLOCK (0 << 18) +#define ADC_CCR_PRESC_DIV2 (1 << 18) +#define ADC_CCR_PRESC_DIV4 (2 << 18) +#define ADC_CCR_PRESC_DIV6 (3 << 18) +#define ADC_CCR_PRESC_DIV8 (4 << 18) +#define ADC_CCR_PRESC_DIV10 (5 << 18) +#define ADC_CCR_PRESC_DIV12 (6 << 18) +#define ADC_CCR_PRESC_DIV16 (7 << 18) +#define ADC_CCR_PRESC_DIV32 (8 << 18) +#define ADC_CCR_PRESC_DIV64 (9 << 18) +#define ADC_CCR_PRESC_DIV128 (10 << 18) +#define ADC_CCR_PRESC_DIV256 (11 << 18) +#endif /* !defined(STM32F3XX) */ + +/* F3 headers do not define the following macros, L4 headers do.*/ +#if !defined(ADC_CCR_VREFEN) || defined(__DOXYGEN__) +#define ADC_CCR_VREFEN (1 << 22) +#endif + +#if !defined(ADC_CCR_TSEN) || defined(__DOXYGEN__) +#define ADC_CCR_TSEN (1 << 23) +#endif + +#if !defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__) +#define ADC_CCR_VBATEN (1 << 24) +#endif +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Enables the ADC master/slave mode. + * @note In dual mode only ADCD1 and ADCD3 are available. + */ +#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_DUAL_MODE FALSE +#endif + +/** + * @brief Makes the ADC samples type an 8bits one. + * @note 10 and 12 bits sampling mode must not be used when this option + * is enabled. + */ +#if !defined(STM32_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__) +#define STM32_ADC_COMPACT_SAMPLES FALSE +#endif + +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC2 driver enable switch. + * @details If set to @p TRUE the support for ADC2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC2 FALSE +#endif + +/** + * @brief ADC3 driver enable switch. + * @details If set to @p TRUE the support for ADC3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC3 FALSE +#endif +/** + * @brief ADC4 driver enable switch. + * @details If set to @p TRUE the support for ADC4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC4) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC4 FALSE +#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 ADC4 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC4_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC1/ADC2 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC3 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC4 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC4_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 + +/** + * @brief ADC4 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC4_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 +#endif + +#if defined(STM32F3XX) || defined(__DOXYGEN__) +/** + * @brief ADC1/ADC2 clock source and mode. + */ +#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#endif + +/** + * @brief ADC3/ADC4 clock source and mode. + */ +#if !defined(STM32_ADC_ADC34_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#endif +#endif /* defined(STM32F3XX) */ + +#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(__DOXYGEN__) +/** + * @brief ADC1/ADC2/ADC3 clock source and mode. + */ +#if !defined(STM32_ADC_ADC123_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#endif + +/** + * @brief ADC1/ADC2/ADC3 clock prescaler. + */ +#if !defined(STM32_ADC_ADC123_PRESC) || defined(__DOXYGEN__) +#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 +#endif +#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */ + +#if defined(STM32G4XX) || defined(__DOXYGEN__) +/** + * @brief ADC1/ADC2 clock source and mode. + */ +#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#endif + +/** + * @brief ADC3/ADC4/ADC5 clock source and mode. + */ +#if !defined(STM32_ADC_ADC345_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC345_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#endif + +/** + * @brief ADC1/ADC2 clock prescaler. + */ +#if !defined(STM32_ADC_ADC12_PRESC) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2 +#endif + +/** + * @brief ADC3/ADC4/ADC5 clock prescaler. + */ +#if !defined(STM32_ADC_ADC345_PRESC) || defined(__DOXYGEN__) +#define STM32_ADC_ADC345_PRESC ADC_CCR_PRESC_DIV2 +#endif +#endif /* defined(STM32G4XX) */ + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Supported devices checks.*/ +#if !defined(STM32F3XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) && \ + !defined(STM32G4XX) +#error "ADCv3 only supports F3, L4, L4+ and G4 STM32 devices" +#endif + +#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) || \ + defined(__DOXYGEN__) +#define STM32_ADCV3_OVERSAMPLING TRUE +#else +#define STM32_ADCV3_OVERSAMPLING FALSE +#endif + +/* Registry checks.*/ +#if !defined(STM32_HAS_ADC1) || !defined(STM32_HAS_ADC2) || \ + !defined(STM32_HAS_ADC3) || !defined(STM32_HAS_ADC4) +#error "STM32_HAS_ADCx not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) || \ + (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_HANDLER)) || \ + (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_HANDLER)) || \ + (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_HANDLER)) +#error "STM32_ADCx_HANDLER not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) || \ + (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_NUMBER)) || \ + (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_NUMBER)) || \ + (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_NUMBER)) +#error "STM32_ADCx_NUMBER not defined in registry" +#endif + +#if !STM32_DMA_SUPPORTS_DMAMUX +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_DMA_MSK)) || \ + (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_DMA_MSK)) || \ + (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_DMA_MSK)) || \ + (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_DMA_MSK)) +#error "STM32_ADCx_DMA_MSK not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_DMA_CHN)) || \ + (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_DMA_CHN)) || \ + (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_DMA_CHN)) || \ + (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_DMA_CHN)) +#error "STM32_ADCx_DMA_CHN not defined in registry" +#endif +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* Units 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_ADC4 && !STM32_HAS_ADC4 +#error "ADC4 not present in the selected device" +#endif + +/* Units checks related to dual mode.*/ +#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC1 && !STM32_HAS_ADC2 +#error "ADC2 not present in the selected device, required for dual mode" +#endif + +#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC3 && !STM32_HAS_ADC4 +#error "ADC4 not present in the selected device, required for dual mode" +#endif + +#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC2 +#error "ADC2 cannot be used in dual mode" +#endif + +#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC4 +#error "ADC4 cannot be used in dual mode" +#endif + +/* At least one ADC must be assigned.*/ +#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && \ + !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +/* ISR arrangements checks.*/ +#if STM32_HAS_ADC1 && STM32_HAS_ADC2 +#if STM32_ADC1_NUMBER != STM32_ADC2_NUMBER +#error "ADCv3 driver expects STM32_ADC1_NUMBER == STM32_ADC2_NUMBER from registry" +#endif +#endif + +/* ADC IRQ priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC2" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC3" +#endif + +#if STM32_ADC_USE_ADC4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC4" +#endif + +/* DMA IRQ priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +#if STM32_ADC_USE_ADC2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC2 DMA" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC3 DMA" +#endif + +#if STM32_ADC_USE_ADC4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC4_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC4 DMA" +#endif + +/* DMA priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC2" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC3" +#endif + +#if STM32_ADC_USE_ADC4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC4" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM) +#error "ADC1 DMA stream not defined" +#endif + +#if STM32_ADC_USE_ADC2 && !defined(STM32_ADC_ADC2_DMA_STREAM) +#error "ADC2 DMA stream not defined" +#endif + +#if STM32_ADC_USE_ADC3 && !defined(STM32_ADC_ADC3_DMA_STREAM) +#error "ADC3 DMA stream not defined" +#endif + +#if STM32_ADC_USE_ADC4 && !defined(STM32_ADC_ADC4_DMA_STREAM) +#error "ADC4 DMA stream not defined" +#endif + +#if STM32_DMA_SUPPORTS_DMAMUX + +#else /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* Check on the validity of the assigned DMA channels.*/ +#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 + +#if STM32_ADC_USE_ADC4 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC4_DMA_STREAM, STM32_ADC4_DMA_MSK) +#error "invalid DMA stream associated to ADC4" +#endif + +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* ADC clock prescaler checks.*/ +#if defined(STM32F3XX) +#endif /* defined(STM32F3XX) */ + +#if defined(STM32L4XX) || defined(STM32L4XXP) +#if STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV2 +#define ADC123_PRESC_VALUE 2 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV4 +#define ADC123_PRESC_VALUE 4 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV6 +#define ADC123_PRESC_VALUE 6 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV8 +#define ADC123_PRESC_VALUE 8 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV10 +#define ADC123_PRESC_VALUE 10 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV12 +#define ADC123_PRESC_VALUE 12 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV16 +#define ADC123_PRESC_VALUE 16 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV32 +#define ADC123_PRESC_VALUE 32 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV64 +#define ADC123_PRESC_VALUE 64 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV128 +#define ADC123_PRESC_VALUE 128 +#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV256 +#define ADC123_PRESC_VALUE 256 +#error "invalid clock divider selected for STM32_ADC_ADC12_PRESC" +#endif +#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */ + +#if defined(STM32G4XX) +#if STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV2 +#define ADC12_PRESC_VALUE 2 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV4 +#define ADC12_PRESC_VALUE 4 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV6 +#define ADC12_PRESC_VALUE 6 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV8 +#define ADC12_PRESC_VALUE 8 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV10 +#define ADC12_PRESC_VALUE 10 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV12 +#define ADC12_PRESC_VALUE 12 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV16 +#define ADC12_PRESC_VALUE 16 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV32 +#define ADC12_PRESC_VALUE 32 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV64 +#define ADC12_PRESC_VALUE 64 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV128 +#define ADC12_PRESC_VALUE 128 +#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV256 +#define ADC12_PRESC_VALUE 256 +#error "invalid clock divider selected for STM32_ADC_ADC12_PRESC" +#endif + +#if STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV2 +#define ADC345_PRESC_VALUE 2 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV4 +#define ADC345_PRESC_VALUE 4 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV6 +#define ADC345_PRESC_VALUE 6 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV8 +#define ADC345_PRESC_VALUE 8 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV10 +#define ADC345_PRESC_VALUE 10 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV12 +#define ADC345_PRESC_VALUE 12 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV16 +#define ADC345_PRESC_VALUE 16 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV32 +#define ADC345_PRESC_VALUE 32 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV64 +#define ADC345_PRESC_VALUE 64 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV128 +#define ADC345_PRESC_VALUE 128 +#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV256 +#define ADC345_PRESC_VALUE 256 +#error "invalid clock divider selected for STM32_ADC_ADC345_PRESC" +#endif +#endif /* defined(STM32G4XX) */ + +/* ADC clock source checks.*/ +#if defined(STM32F3XX) +#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC12_CLOCK STM32_ADC12CLK +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC12_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC12_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC12_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" +#endif + +#if STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC34_CLOCK STM32_ADC34CLK +#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC34_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC34_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC34_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC34_CLOCK_MODE" +#endif + +#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +#if STM32_ADC34_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC34_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif +#endif /* defined(STM32F3XX) */ + +#if defined(STM32L4XX) || defined(STM32L4XXP) +#if STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC123_CLOCK (STM32_ADCCLK / ADC123_PRESC_VALUE) +#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC123_CLOCK (STM32_ADCCLK / 1) +#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC123_CLOCK (STM32_ADCCLK / 2) +#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC123_CLOCK (STM32_ADCCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC123_CLOCK_MODE" +#endif + +#if STM32_ADC123_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC123_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif +#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */ + +#if defined(STM32G4XX) +#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC12_CLOCK (STM32_ADC12CLK / ADC12_PRESC_VALUE) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC12_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC12_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC12_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" +#endif + +#if STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC345_CLOCK (STM32_ADC345CLK / ADC345_PRESC_VALUE) +#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC345_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC345_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC345_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC345_CLOCK_MODE" +#endif + +#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +#if STM32_ADC345_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC345_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif +#endif /* defined(STM32G4XX) */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +#if !STM32_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__) +typedef uint16_t adcsample_t; +#else +typedef uint8_t adcsample_t; +#endif + +/** + * @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. */ + ADC_ERR_AWD1 = 2, /**< Watchdog 1 triggered. */ + ADC_ERR_AWD2 = 3, /**< Watchdog 2 triggered. */ + ADC_ERR_AWD3 = 4 /**< Watchdog 3 triggered. */ +} adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) +#define adc_lld_driver_fields \ + /* Pointer to the master ADCx registers block.*/ \ + ADC_TypeDef *adcm; \ + /* Pointer to the slave ADCx registers block.*/ \ + ADC_TypeDef *adcs; \ + /* Pointer to the common ADCx_y registers block.*/ \ + ADC_Common_TypeDef *adcc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode +#else +#define adc_lld_driver_fields \ + /* Pointer to the master ADCx registers block.*/ \ + ADC_TypeDef *adcm; \ + /* Pointer to the slave ADCx registers block.*/ \ + ADC_Common_TypeDef *adcc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode +#endif + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* ADC DIFSEL register initialization data.*/ \ + uint32_t difsel + +/** + * @brief Low level fields of the ADC group configuration structure. + */ +#if (STM32_ADCV3_OVERSAMPLING == TRUE) || defined(__DOXYGEN__) +#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) +#define adc_lld_configuration_group_fields \ + /* ADC CFGR register initialization data. \ + NOTE: The bits DMAEN and DMACFG are enforced internally \ + to the driver, keep them to zero. \ + NOTE: The bits @p ADC_CFGR_CONT or @p ADC_CFGR_DISCEN must be \ + specified in continuous mode or if the buffer depth is \ + greater than one.*/ \ + uint32_t cfgr; \ + /* ADC CFGR2 register initialization data.*/ \ + uint32_t cfgr2; \ + /* ADC TR1 register initialization data.*/ \ + uint32_t tr1; \ + /* ADC TR2 register initialization data.*/ \ + uint32_t tr2; \ + /* ADC TR3 register initialization data.*/ \ + uint32_t tr3; \ + /* ADC AWD2CR register initialization data.*/ \ + uint32_t awd2cr; \ + /* ADC AWD3CR register initialization data.*/ \ + uint32_t awd3cr; \ + /* ADC CCR register initialization data. \ + NOTE: Put this field to zero if not using oversampling.*/ \ + uint32_t ccr; \ + /* ADC SMPRx registers initialization data.*/ \ + uint32_t smpr[2]; \ + /* ADC SQRx register initialization data.*/ \ + uint32_t sqr[4]; \ + /* Slave ADC SMPRx registers initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t ssmpr[2]; \ + /* Slave ADC SQRx register initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t ssqr[4] +#else /* STM32_ADC_DUAL_MODE == FALSE */ +#define adc_lld_configuration_group_fields \ + uint32_t cfgr; \ + uint32_t cfgr2; \ + uint32_t tr1; \ + uint32_t tr2; \ + uint32_t tr3; \ + uint32_t awd2cr; \ + uint32_t awd3cr; \ + uint32_t smpr[2]; \ + uint32_t sqr[4] +#endif /* STM32_ADC_DUAL_MODE == FALSE */ + +#else /* STM32_ADCV3_OVERSAMPLING == FALSE */ +#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) +#define adc_lld_configuration_group_fields \ + uint32_t cfgr; \ + uint32_t tr1; \ + uint32_t tr2; \ + uint32_t tr3; \ + uint32_t awd2cr; \ + uint32_t awd3cr; \ + uint32_t ccr; \ + uint32_t smpr[2]; \ + uint32_t sqr[4]; \ + uint32_t ssmpr[2]; \ + uint32_t ssqr[4] +#else /* STM32_ADC_DUAL_MODE == FALSE */ +#define adc_lld_configuration_group_fields \ + uint32_t cfgr; \ + uint32_t tr1; \ + uint32_t tr2; \ + uint32_t tr3; \ + uint32_t awd2cr; \ + uint32_t awd3cr; \ + uint32_t smpr[2]; \ + uint32_t sqr[4] +#endif /* STM32_ADC_DUAL_MODE == FALSE */ +#endif /* STM32_ADCV3_OVERSAMPLING == FALSE */ + +/** + * @name Threshold registers initializers + * @{ + */ +#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low)) +#define ADC_TR_DISABLED ADC_TR(0U, 0x0FFFU) +#define ADC_AWDCR_ENABLE(n) (1U << (n)) +/** @} */ + +/** + * @name Sequences building helper macros + * @{ + */ +/** + * @brief Number of channels in a conversion sequence. + */ +#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 0) + +#define ADC_SQR1_SQ1_N(n) ((n) << 6) /**< @brief 1st channel in seq. */ +#define ADC_SQR1_SQ2_N(n) ((n) << 12) /**< @brief 2nd channel in seq. */ +#define ADC_SQR1_SQ3_N(n) ((n) << 18) /**< @brief 3rd channel in seq. */ +#define ADC_SQR1_SQ4_N(n) ((n) << 24) /**< @brief 4th channel in seq. */ + +#define ADC_SQR2_SQ5_N(n) ((n) << 0) /**< @brief 5th channel in seq. */ +#define ADC_SQR2_SQ6_N(n) ((n) << 6) /**< @brief 6th channel in seq. */ +#define ADC_SQR2_SQ7_N(n) ((n) << 12) /**< @brief 7th channel in seq. */ +#define ADC_SQR2_SQ8_N(n) ((n) << 18) /**< @brief 8th channel in seq. */ +#define ADC_SQR2_SQ9_N(n) ((n) << 24) /**< @brief 9th channel in seq. */ + +#define ADC_SQR3_SQ10_N(n) ((n) << 0) /**< @brief 10th channel in seq.*/ +#define ADC_SQR3_SQ11_N(n) ((n) << 6) /**< @brief 11th channel in seq.*/ +#define ADC_SQR3_SQ12_N(n) ((n) << 12) /**< @brief 12th channel in seq.*/ +#define ADC_SQR3_SQ13_N(n) ((n) << 18) /**< @brief 13th channel in seq.*/ +#define ADC_SQR3_SQ14_N(n) ((n) << 24) /**< @brief 14th channel in seq.*/ + +#define ADC_SQR4_SQ15_N(n) ((n) << 0) /**< @brief 15th channel in seq.*/ +#define ADC_SQR4_SQ16_N(n) ((n) << 6) /**< @brief 16th channel in seq.*/ +/** @} */ + +/** + * @name Sampling rate settings helper macros + * @{ + */ +#define ADC_SMPR1_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */ +#define ADC_SMPR1_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ +#define ADC_SMPR1_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ +#define ADC_SMPR1_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ +#define ADC_SMPR1_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ +#define ADC_SMPR1_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ +#define ADC_SMPR1_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ +#define ADC_SMPR1_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ +#define ADC_SMPR1_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ +#define ADC_SMPR1_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ + +#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ +#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ +#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ +#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ +#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ +#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ +#define ADC_SMPR2_SMP_AN16(n) ((n) << 18) /**< @brief AN16 sampling time. */ +#define ADC_SMPR2_SMP_AN17(n) ((n) << 21) /**< @brief AN17 sampling time. */ +#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 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 + +#if STM32_ADC_USE_ADC4 && !defined(__DOXYGEN__) +extern ADCDriver ADCD4; +#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 adcSTM32EnableVREF(ADCDriver *adcp); + void adcSTM32DisableVREF(ADCDriver *adcp); + void adcSTM32EnableTS(ADCDriver *adcp); + void adcSTM32DisableTS(ADCDriver *adcp); + void adcSTM32EnableVBAT(ADCDriver *adcp); + void adcSTM32DisableVBAT(ADCDriver *adcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv3/notes.txt b/os/hal/ports/STM32/LLD/ADCv3/notes.txt index fbfe6c224a..24c77eb5c8 100644 --- a/os/hal/ports/STM32/LLD/ADCv3/notes.txt +++ b/os/hal/ports/STM32/LLD/ADCv3/notes.txt @@ -1,22 +1,22 @@ -STM32 ADCv3 driver. - -Driver capability: - -- Supports the STM32 "fast" ADC found on F3, L4, L4+ and G4 sub-families. - -The file registry must export: - -STM32_HAS_ADCx - ADCx presence flag (1..4). -STM32_ADC1_HANDLER - IRQ vector name for ADC1. -STM32_ADC1_NUMBER - IRQ vector number for ADC1. -STM32_ADC2_HANDLER - IRQ vector name for ADC2. -STM32_ADC2_NUMBER - IRQ vector number for ADC2. -STM32_ADC3_HANDLER - IRQ vector name for ADC3. -STM32_ADC3_NUMBER - IRQ vector number for ADC3. -STM32_ADC4_HANDLER - IRQ vector name for ADC4. -STM32_ADC4_NUMBER - IRQ vector number for ADC4. - -If there is no DMAMUX then the file registry must export also: - -STM32_ADCx_DMA_MSK - Mask of the compatible DMA channels (1..4). -STM32_ADCx_DMA_CHN - Mask of the channels mapping (1..4). +STM32 ADCv3 driver. + +Driver capability: + +- Supports the STM32 "fast" ADC found on F3, L4, L4+ and G4 sub-families. + +The file registry must export: + +STM32_HAS_ADCx - ADCx presence flag (1..4). +STM32_ADC1_HANDLER - IRQ vector name for ADC1. +STM32_ADC1_NUMBER - IRQ vector number for ADC1. +STM32_ADC2_HANDLER - IRQ vector name for ADC2. +STM32_ADC2_NUMBER - IRQ vector number for ADC2. +STM32_ADC3_HANDLER - IRQ vector name for ADC3. +STM32_ADC3_NUMBER - IRQ vector number for ADC3. +STM32_ADC4_HANDLER - IRQ vector name for ADC4. +STM32_ADC4_NUMBER - IRQ vector number for ADC4. + +If there is no DMAMUX then the file registry must export also: + +STM32_ADCx_DMA_MSK - Mask of the compatible DMA channels (1..4). +STM32_ADCx_DMA_CHN - Mask of the channels mapping (1..4). diff --git a/os/hal/ports/STM32/LLD/ADCv4/driver.mk b/os/hal/ports/STM32/LLD/ADCv4/driver.mk index 91bc8859dc..0f9cd840dd 100644 --- a/os/hal/ports/STM32/LLD/ADCv4/driver.mk +++ b/os/hal/ports/STM32/LLD/ADCv4/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4 diff --git a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c index a7efc91839..d58b9407b4 100644 --- a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c +++ b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c @@ -1,848 +1,848 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv4/hal_adc_lld.c - * @brief STM32 ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_ADC_DUAL_MODE == TRUE -#define ADC12_CCR_DUAL ADC_CCR_DUAL_REG_SIMULT -#if STM32_ADC_SAMPLES_SIZE == 8 -/* Compact type dual mode, 2x8-bit.*/ -#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) -#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_BYTE | STM32_BDMA_CR_PSIZE_BYTE) -#define ADC_DMA_DAMDF ADC_CCR_DAMDF_BYTE - -#else /* STM32_ADC_SAMPLES_SIZE == 16 */ -/* Large type dual mode, 2x16bit.*/ -#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) -#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_HWORD | STM32_BDMA_CR_PSIZE_HWORD) -#define ADC_DMA_DAMDF ADC_CCR_DAMDF_HWORD -#endif /* STM32_ADC_SAMPLES_SIZE == 8 */ - -#else /* STM32_ADC_DUAL_MODE == FALSE */ -#define ADC12_CCR_DUAL ADC_CCR_DUAL_INDEPENDENT -#if STM32_ADC_SAMPLES_SIZE == 8 -/* Compact type single mode, 8-bit.*/ -#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) -#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_BYTE | STM32_BDMA_CR_PSIZE_BYTE) -#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED -#elif STM32_ADC_SAMPLES_SIZE == 32 -#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) -#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_WORD | STM32_BDMA_CR_PSIZE_WORD) -#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED -#else /* STM32_ADC_SAMPLES_SIZE == 16 */ -/* Large type single mode, 16-bit.*/ -#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) -#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_HWORD | STM32_BDMA_CR_PSIZE_HWORD) -#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED -#endif /* STM32_ADC_SAMPLES_SIZE == 8 */ -#endif /* STM32_ADC_DUAL_MODE == FALSE */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC12 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/** @brief ADC3 driver identifier.*/ -#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) -ADCDriver ADCD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const ADCConfig default_config = { - .difsel = 0U -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Enables the ADC voltage regulator. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_vreg_on(ADCDriver *adcp) { - - adcp->adcm->CR = ADC_CR_ADVREGEN; -#if STM32_ADC_DUAL_MODE - if (&ADCD1 == adcp) { - adcp->adcs->CR = ADC_CR_ADVREGEN; - } -#endif - osalSysPolledDelayX(OSAL_US2RTC(STM32_SYS_CK, 10U)); -} - -/** - * @brief Disables the ADC voltage regulator. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_vreg_off(ADCDriver *adcp) { - - adcp->adcm->CR = ADC_CR_DEEPPWD; -#if STM32_ADC_DUAL_MODE - if (&ADCD1 == adcp) { - adcp->adcs->CR = ADC_CR_DEEPPWD; - } -#endif -} - -/** - * @brief Enables the ADC analog circuit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_analog_on(ADCDriver *adcp) { - - adcp->adcm->ISR = ADC_ISR_ADRDY; - adcp->adcm->CR |= ADC_CR_ADEN; - while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0U) - ; -#if STM32_ADC_DUAL_MODE - if (&ADCD1 == adcp) { - adcp->adcs->ISR = ADC_ISR_ADRDY; - adcp->adcs->CR |= ADC_CR_ADEN; - while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0U) - ; - } -#endif -} - -/** - * @brief Disables the ADC analog circuit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_analog_off(ADCDriver *adcp) { - - adcp->adcm->CR |= ADC_CR_ADDIS; - while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0U) - ; -#if STM32_ADC_DUAL_MODE - if (&ADCD1 == adcp) { - adcp->adcs->CR |= ADC_CR_ADDIS; - while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0U) - ; - } -#endif -} - -/** - * @brief Calibrates and ADC unit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_calibrate(ADCDriver *adcp) { - - osalDbgAssert(adcp->adcm->CR == ADC_CR_ADVREGEN, "invalid register state"); - - adcp->adcm->CR &= ~(ADC_CR_ADCALDIF | ADC_CR_ADCALLIN); - adcp->adcm->CR |= adcp->config->calibration & (ADC_CR_ADCALDIF | - ADC_CR_ADCALLIN); - adcp->adcm->CR |= ADC_CR_ADCAL; - while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0U) - ; -#if STM32_ADC_DUAL_MODE - if (&ADCD1 == adcp) { - osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN, "invalid register state"); - - adcp->adcs->CR &= ~(ADC_CR_ADCALDIF | ADC_CR_ADCALLIN); - adcp->adcs->CR |= adcp->config->calibration & (ADC_CR_ADCALDIF | - ADC_CR_ADCALLIN); - adcp->adcs->CR |= ADC_CR_ADCAL; - while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0U) - ; - } -#endif -} - -/** - * @brief Stops an ongoing conversion, if any. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_stop_adc(ADCDriver *adcp) { - - if (adcp->adcm->CR & ADC_CR_ADSTART) { - adcp->adcm->CR |= ADC_CR_ADSTP; - while (adcp->adcm->CR & ADC_CR_ADSTP) - ; - } - adcp->adcm->PCSEL = 0U; -} - -#if (STM32_ADC_USE_ADC12 == TRUE) || defined(__DOXYGEN__) -/** - * @brief ADC DMA 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_dma_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - -#if (STM32_ADC_USE_ADC3 == TRUE) || defined(__DOXYGEN__) -/** - * @brief ADC BDMA 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_bdma_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & STM32_BDMA_ISR_TEIF) != 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_BDMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_BDMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} -#endif /* STM32_ADC_USE_ADC3 == TRUE */ - -/** - * @brief ADC IRQ service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] isr content of the ISR register - */ -static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - adcerror_t emask = 0U; - - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the state is checked too.*/ - if ((isr & ADC_ISR_OVR) && (adcp->state == ADC_ACTIVE)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - emask |= ADC_ERR_OVERFLOW; - } - if (isr & ADC_ISR_AWD1) { - /* Analog watchdog 1 error.*/ - emask |= ADC_ERR_AWD1; - } - if (isr & ADC_ISR_AWD2) { - /* Analog watchdog 2 error.*/ - emask |= ADC_ERR_AWD2; - } - if (isr & ADC_ISR_AWD3) { - /* Analog watchdog 3 error.*/ - emask |= ADC_ERR_AWD3; - } - if (emask != 0U) { - _adc_isr_error_code(adcp, emask); - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (STM32_ADC_USE_ADC12 == TRUE) || defined(__DOXYGEN__) -/** - * @brief ADC1/ADC2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC12_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - /* Handle ADC1 ISR first in adc_lld_serve_interrupt. */ - isr = ADC1->ISR; - ADC1->ISR = isr; -#if defined(STM32_ADC_ADC12_IRQ_HOOK) - STM32_ADC_ADC12_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD1, isr); - - /* Handle ADC2 ISR next in adc_lld_serve_interrupt. */ -#if STM32_ADC_DUAL_MODE - isr |= ADC2->ISR; - ADC2->ISR = isr; -#if defined(STM32_ADC_ADC12_IRQ_HOOK) - STM32_ADC_ADC12_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD1, isr); -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - -#if (STM32_ADC_USE_ADC3 == TRUE) || defined(__DOXYGEN__) -/** - * @brief ADC3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC3_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC3->ISR; - ADC3->ISR = isr; -#if defined(STM32_ADC_ADC3_IRQ_HOOK) - STM32_ADC_ADC3_IRQ_HOOK -#endif - adc_lld_serve_interrupt(&ADCD3, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_ADC3 == TRUE */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC12 == TRUE - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adcc = ADC12_COMMON; - ADCD1.adcm = ADC1; -#if STM32_ADC_DUAL_MODE - ADCD1.adcs = ADC2; -#endif - ADCD1.data.dma = NULL; - ADCD1.dmamode = ADC12_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - nvicEnableVector(STM32_ADC12_NUMBER, STM32_ADC_ADC12_IRQ_PRIORITY); -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - -#if STM32_ADC_USE_ADC3 == TRUE - /* Driver initialization.*/ - adcObjectInit(&ADCD3); - ADCD3.adcc = ADC3_COMMON; - ADCD3.adcm = ADC3; - ADCD3.data.bdma = NULL; - ADCD3.dmamode = ADC3_BDMA_SIZE | - STM32_BDMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | - STM32_BDMA_CR_DIR_P2M | - STM32_BDMA_CR_MINC | STM32_BDMA_CR_TCIE | - STM32_BDMA_CR_TEIE; - nvicEnableVector(STM32_ADC3_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY); -#endif /* STM32_ADC_USE_ADC3 == TRUE */ - - /* ADC units pre-initializations.*/ -#if (STM32_HAS_ADC1 == TRUE) && (STM32_HAS_ADC2 == TRUE) -#if STM32_ADC_USE_ADC12 == TRUE - rccEnableADC12(true); - rccResetADC12(); - ADC12_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF | ADC12_CCR_DUAL; - rccDisableADC12(); -#endif -#if STM32_ADC_USE_ADC3 == TRUE - rccEnableADC3(true); - rccResetADC3(); - ADC3_COMMON->CCR = STM32_ADC_ADC3_CLOCK_MODE; - rccDisableADC3(); -#endif -#endif -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - /* Handling the default configuration.*/ - if (adcp->config == NULL) { - adcp->config = &default_config; - } - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC12 == TRUE - if (&ADCD1 == adcp) { - adcp->data.dma = dmaStreamAllocI(STM32_ADC_ADC12_DMA_STREAM, - STM32_ADC_ADC12_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->data.dma != NULL, "unable to allocate stream"); - rccEnableADC12(true); - dmaSetRequestSource(adcp->data.dma, STM32_DMAMUX1_ADC1); - - /* Setting DMA peripheral-side pointer.*/ -#if STM32_ADC_DUAL_MODE - dmaStreamSetPeripheral(adcp->data.dma, &adcp->adcc->CDR); -#else - dmaStreamSetPeripheral(adcp->data.dma, &adcp->adcm->DR); -#endif - - /* Differential channels setting.*/ -#if STM32_ADC_DUAL_MODE - adcp->adcm->DIFSEL = adcp->config->difsel; - adcp->adcs->DIFSEL = adcp->config->difsel; -#else - adcp->adcm->DIFSEL = adcp->config->difsel; -#endif - } -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - -#if STM32_ADC_USE_ADC3 == TRUE - if (&ADCD3 == adcp) { - adcp->data.bdma = bdmaStreamAllocI(STM32_ADC_ADC3_BDMA_STREAM, - STM32_ADC_ADC3_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_bdma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->data.bdma != NULL, "unable to allocate stream"); - rccEnableADC3(true); - bdmaSetRequestSource(adcp->data.bdma, STM32_DMAMUX2_ADC3_REQ); - - /* Setting DMA peripheral-side pointer.*/ - bdmaStreamSetPeripheral(adcp->data.bdma, &adcp->adcm->DR); - - /* Differential channels setting.*/ - adcp->adcm->DIFSEL = adcp->config->difsel; - } -#endif /* STM32_ADC_USE_ADC3 == TRUE */ - - /* Master ADC calibration.*/ - adc_lld_vreg_on(adcp); - adc_lld_calibrate(adcp); - - /* Configure the ADC boost. */ -#if STM32_ADC_USE_ADC12 == TRUE - if (&ADCD1 == adcp) { - adcp->adcm->CR |= STM32_ADC12_BOOST; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR |= STM32_ADC12_BOOST; -#endif - } -#endif - -#if STM32_ADC_USE_ADC3 == TRUE - if (&ADCD3 == adcp) { - adcp->adcm->CR |= STM32_ADC3_BOOST; - } -#endif - - /* Master ADC enabled here in order to reduce conversions latencies.*/ - adc_lld_analog_on(adcp); - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - - /* Stopping the ongoing conversion, if any.*/ - adc_lld_stop_adc(adcp); - - /* Disabling ADC analog circuit and regulator.*/ - adc_lld_analog_off(adcp); - adc_lld_vreg_off(adcp); - -#if STM32_ADC_USE_ADC12 == TRUE - if (&ADCD1 == adcp) { - - /* Releasing the associated DMA channel.*/ - dmaStreamFreeI(adcp->data.dma); - adcp->data.dma = NULL; - - /* Resetting CCR options except default ones.*/ - adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF | ADC12_CCR_DUAL; - rccDisableADC12(); - } -#endif - -#if STM32_ADC_USE_ADC3 == TRUE - if (&ADCD3 == adcp) { - - /* Releasing the associated BDMA channel.*/ - bdmaStreamFreeI(adcp->data.bdma); - adcp->data.bdma = NULL; - - /* Resetting CCR options except default ones.*/ - adcp->adcc->CCR = STM32_ADC_ADC3_CLOCK_MODE; - rccDisableADC3(); - } -#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 dmamode, cfgr = 0U; - const ADCConversionGroup *grpp = adcp->grpp; - -#if STM32_ADC_USE_ADC12 == TRUE -#if STM32_ADC_DUAL_MODE - uint32_t ccr; -#endif - if (&ADCD1 == adcp) { -#if STM32_ADC_DUAL_MODE - ccr = grpp->ccr & ~(ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK); - osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0), - "odd number of channels in dual mode"); -#endif - - /* Calculating control registers values.*/ - dmamode = adcp->dmamode; - if (grpp->circular) { - dmamode |= STM32_DMA_CR_CIRC; - cfgr = grpp->cfgr | ADC_CFGR_DMNGT_CIRCULAR; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - dmamode |= STM32_DMA_CR_HTIE; - } - } - else { - cfgr = grpp->cfgr | ADC_CFGR_DMNGT_ONESHOT; - } - - /* DMA setup.*/ - dmaStreamSetMemory0(adcp->data.dma, adcp->samples); -#if STM32_ADC_DUAL_MODE - dmaStreamSetTransactionSize(adcp->data.dma, ((uint32_t)grpp->num_channels / 2U) * - (uint32_t)adcp->depth); -#else - dmaStreamSetTransactionSize(adcp->data.dma, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); -#endif - dmaStreamSetMode(adcp->data.dma, dmamode); - dmaStreamEnable(adcp->data.dma); - } -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - -#if STM32_ADC_USE_ADC3 == TRUE - if (&ADCD3 == adcp) { - /* Calculating control registers values.*/ - dmamode = adcp->dmamode; - if (grpp->circular) { - dmamode |= STM32_BDMA_CR_CIRC; - cfgr = grpp->cfgr | ADC_CFGR_DMNGT_CIRCULAR; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - dmamode |= STM32_BDMA_CR_HTIE; - } - } - else { - cfgr = grpp->cfgr | ADC_CFGR_DMNGT_ONESHOT; - } - - /* DMA setup.*/ - bdmaStreamSetMemory(adcp->data.bdma, adcp->samples); - bdmaStreamSetTransactionSize(adcp->data.bdma, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - bdmaStreamSetMode(adcp->data.bdma, dmamode); - bdmaStreamEnable(adcp->data.bdma); - } -#endif /* STM32_ADC_USE_ADC3 == TRUE */ - - /* ADC setup, if it is defined a callback for the analog watch dog then it - is enabled.*/ - /* clear AWD1..3 flags */ - adcp->adcm->ISR = adcp->adcm->ISR; - /* If a callback is set enable the overflow and analog watch dog interrupts. */ - if (grpp->error_cb != NULL) { - adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE - | ADC_IER_AWD2IE - | ADC_IER_AWD3IE; - } -#if STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE - /* Configuration for dual mode ADC12 */ - if (&ADCD1 == adcp) { - /* clear AWD1..3 flags */ - adcp->adcs->ISR = adcp->adcs->ISR; - /* If a callback is set enable the overflow and analog watch dog interrupts. */ - if (grpp->error_cb != NULL) { - adcp->adcs->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE - | ADC_IER_AWD2IE - | ADC_IER_AWD3IE; - /* Configuring the CCR register with the user-specified settings - in the conversion group configuration structure, static settings are - preserved.*/ - adcp->adcc->CCR = (adcp->adcc->CCR & - (ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK | ADC_CCR_DUAL_MASK)) | ccr; - - adcp->adcm->CFGR2 = grpp->cfgr2; - adcp->adcm->PCSEL = grpp->pcsel; - adcp->adcm->LTR1 = grpp->ltr1; - adcp->adcm->HTR1 = grpp->htr1; - adcp->adcm->LTR2 = grpp->ltr2; - adcp->adcm->HTR2 = grpp->htr2; - adcp->adcm->LTR3 = grpp->ltr3; - adcp->adcm->HTR3 = grpp->htr3; - adcp->adcm->AWD2CR = grpp->awd2cr; - adcp->adcm->AWD3CR = grpp->awd3cr; - adcp->adcm->SMPR1 = grpp->smpr[0]; - adcp->adcm->SMPR2 = grpp->smpr[1]; - adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); - adcp->adcm->SQR2 = grpp->sqr[1]; - adcp->adcm->SQR3 = grpp->sqr[2]; - adcp->adcm->SQR4 = grpp->sqr[3]; - adcp->adcs->CFGR2 = grpp->cfgr2; - adcp->adcs->PCSEL = grpp->pcsel; - adcp->adcs->LTR1 = grpp->sltr1; - adcp->adcs->HTR1 = grpp->shtr1; - adcp->adcs->LTR2 = grpp->sltr2; - adcp->adcs->HTR2 = grpp->shtr2; - adcp->adcs->LTR3 = grpp->sltr3; - adcp->adcs->HTR3 = grpp->shtr3; - adcp->adcs->AWD2CR = grpp->sawd2cr; - adcp->adcs->AWD3CR = grpp->sawd3cr; - adcp->adcs->SMPR1 = grpp->ssmpr[0]; - adcp->adcs->SMPR2 = grpp->ssmpr[1]; - adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); - adcp->adcs->SQR2 = grpp->ssqr[1]; - adcp->adcs->SQR3 = grpp->ssqr[2]; - adcp->adcs->SQR4 = grpp->ssqr[3]; - - /* ADC configuration.*/ - adcp->adcm->CFGR = cfgr; - adcp->adcs->CFGR = cfgr; - } -} -#endif /* STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE */ - -#if STM32_ADC_DUAL_MODE == FALSE || STM32_ADC_USE_ADC3 == TRUE - /* Configuration for ADC3 and single mode ADC1 */ - - adcp->adcm->CFGR2 = grpp->cfgr2; - adcp->adcm->PCSEL = grpp->pcsel; - adcp->adcm->LTR1 = grpp->ltr1; - adcp->adcm->HTR1 = grpp->htr1; - adcp->adcm->LTR2 = grpp->ltr2; - adcp->adcm->HTR2 = grpp->htr2; - adcp->adcm->LTR3 = grpp->ltr3; - adcp->adcm->HTR3 = grpp->htr3; - adcp->adcm->AWD2CR = grpp->awd2cr; - adcp->adcm->AWD3CR = grpp->awd3cr; - adcp->adcm->SMPR1 = grpp->smpr[0]; - adcp->adcm->SMPR2 = grpp->smpr[1]; - adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); - adcp->adcm->SQR2 = grpp->sqr[1]; - adcp->adcm->SQR3 = grpp->sqr[2]; - adcp->adcm->SQR4 = grpp->sqr[3]; - - /* ADC configuration.*/ - adcp->adcm->CFGR = cfgr; -#endif - - /* Starting conversion.*/ - adcp->adcm->CR |= ADC_CR_ADSTART; -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop_conversion(ADCDriver *adcp) { - -#if STM32_ADC_USE_ADC12 == TRUE - if (&ADCD1 == adcp) { - dmaStreamDisable(adcp->data.dma); - } -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - -#if STM32_ADC_USE_ADC3 == TRUE - if (&ADCD3 == adcp) { - bdmaStreamDisable(adcp->data.bdma); - } -#endif /* STM32_ADC_USE_ADC12 == TRUE */ - - adc_lld_stop_adc(adcp); -} - -/** - * @brief Enables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVREF(ADCDriver *adcp) { - - adcp->adcc->CCR |= ADC_CCR_VREFEN; -} - -/** - * @brief Disables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVREF(ADCDriver *adcp) { - - adcp->adcc->CCR &= ~ADC_CCR_VREFEN; -} - -/** - * @brief Enables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableTS(ADCDriver *adcp) { - - adcp->adcc->CCR |= ADC_CCR_TSEN; -} - -/** - * @brief Disables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableTS(ADCDriver *adcp) { - - adcp->adcc->CCR &= ~ADC_CCR_TSEN; -} - -/** - * @brief Enables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVBAT(ADCDriver *adcp) { - - adcp->adcc->CCR |= ADC_CCR_VBATEN; -} - -/** - * @brief Disables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVBAT(ADCDriver *adcp) { - - adcp->adcc->CCR &= ~ADC_CCR_VBATEN; -} - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv4/hal_adc_lld.c + * @brief STM32 ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_ADC_DUAL_MODE == TRUE +#define ADC12_CCR_DUAL ADC_CCR_DUAL_REG_SIMULT +#if STM32_ADC_SAMPLES_SIZE == 8 +/* Compact type dual mode, 2x8-bit.*/ +#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) +#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_BYTE | STM32_BDMA_CR_PSIZE_BYTE) +#define ADC_DMA_DAMDF ADC_CCR_DAMDF_BYTE + +#else /* STM32_ADC_SAMPLES_SIZE == 16 */ +/* Large type dual mode, 2x16bit.*/ +#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) +#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_HWORD | STM32_BDMA_CR_PSIZE_HWORD) +#define ADC_DMA_DAMDF ADC_CCR_DAMDF_HWORD +#endif /* STM32_ADC_SAMPLES_SIZE == 8 */ + +#else /* STM32_ADC_DUAL_MODE == FALSE */ +#define ADC12_CCR_DUAL ADC_CCR_DUAL_INDEPENDENT +#if STM32_ADC_SAMPLES_SIZE == 8 +/* Compact type single mode, 8-bit.*/ +#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) +#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_BYTE | STM32_BDMA_CR_PSIZE_BYTE) +#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED +#elif STM32_ADC_SAMPLES_SIZE == 32 +#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) +#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_WORD | STM32_BDMA_CR_PSIZE_WORD) +#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED +#else /* STM32_ADC_SAMPLES_SIZE == 16 */ +/* Large type single mode, 16-bit.*/ +#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) +#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_HWORD | STM32_BDMA_CR_PSIZE_HWORD) +#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED +#endif /* STM32_ADC_SAMPLES_SIZE == 8 */ +#endif /* STM32_ADC_DUAL_MODE == FALSE */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC12 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/** @brief ADC3 driver identifier.*/ +#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) +ADCDriver ADCD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const ADCConfig default_config = { + .difsel = 0U +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Enables the ADC voltage regulator. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_vreg_on(ADCDriver *adcp) { + + adcp->adcm->CR = ADC_CR_ADVREGEN; +#if STM32_ADC_DUAL_MODE + if (&ADCD1 == adcp) { + adcp->adcs->CR = ADC_CR_ADVREGEN; + } +#endif + osalSysPolledDelayX(OSAL_US2RTC(STM32_SYS_CK, 10U)); +} + +/** + * @brief Disables the ADC voltage regulator. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_vreg_off(ADCDriver *adcp) { + + adcp->adcm->CR = ADC_CR_DEEPPWD; +#if STM32_ADC_DUAL_MODE + if (&ADCD1 == adcp) { + adcp->adcs->CR = ADC_CR_DEEPPWD; + } +#endif +} + +/** + * @brief Enables the ADC analog circuit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_analog_on(ADCDriver *adcp) { + + adcp->adcm->ISR = ADC_ISR_ADRDY; + adcp->adcm->CR |= ADC_CR_ADEN; + while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0U) + ; +#if STM32_ADC_DUAL_MODE + if (&ADCD1 == adcp) { + adcp->adcs->ISR = ADC_ISR_ADRDY; + adcp->adcs->CR |= ADC_CR_ADEN; + while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0U) + ; + } +#endif +} + +/** + * @brief Disables the ADC analog circuit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_analog_off(ADCDriver *adcp) { + + adcp->adcm->CR |= ADC_CR_ADDIS; + while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0U) + ; +#if STM32_ADC_DUAL_MODE + if (&ADCD1 == adcp) { + adcp->adcs->CR |= ADC_CR_ADDIS; + while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0U) + ; + } +#endif +} + +/** + * @brief Calibrates and ADC unit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_calibrate(ADCDriver *adcp) { + + osalDbgAssert(adcp->adcm->CR == ADC_CR_ADVREGEN, "invalid register state"); + + adcp->adcm->CR &= ~(ADC_CR_ADCALDIF | ADC_CR_ADCALLIN); + adcp->adcm->CR |= adcp->config->calibration & (ADC_CR_ADCALDIF | + ADC_CR_ADCALLIN); + adcp->adcm->CR |= ADC_CR_ADCAL; + while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0U) + ; +#if STM32_ADC_DUAL_MODE + if (&ADCD1 == adcp) { + osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN, "invalid register state"); + + adcp->adcs->CR &= ~(ADC_CR_ADCALDIF | ADC_CR_ADCALLIN); + adcp->adcs->CR |= adcp->config->calibration & (ADC_CR_ADCALDIF | + ADC_CR_ADCALLIN); + adcp->adcs->CR |= ADC_CR_ADCAL; + while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0U) + ; + } +#endif +} + +/** + * @brief Stops an ongoing conversion, if any. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_stop_adc(ADCDriver *adcp) { + + if (adcp->adcm->CR & ADC_CR_ADSTART) { + adcp->adcm->CR |= ADC_CR_ADSTP; + while (adcp->adcm->CR & ADC_CR_ADSTP) + ; + } + adcp->adcm->PCSEL = 0U; +} + +#if (STM32_ADC_USE_ADC12 == TRUE) || defined(__DOXYGEN__) +/** + * @brief ADC DMA 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_dma_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + +#if (STM32_ADC_USE_ADC3 == TRUE) || defined(__DOXYGEN__) +/** + * @brief ADC BDMA 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_bdma_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & STM32_BDMA_ISR_TEIF) != 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_BDMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_BDMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} +#endif /* STM32_ADC_USE_ADC3 == TRUE */ + +/** + * @brief ADC IRQ service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] isr content of the ISR register + */ +static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + adcerror_t emask = 0U; + + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the state is checked too.*/ + if ((isr & ADC_ISR_OVR) && (adcp->state == ADC_ACTIVE)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + emask |= ADC_ERR_OVERFLOW; + } + if (isr & ADC_ISR_AWD1) { + /* Analog watchdog 1 error.*/ + emask |= ADC_ERR_AWD1; + } + if (isr & ADC_ISR_AWD2) { + /* Analog watchdog 2 error.*/ + emask |= ADC_ERR_AWD2; + } + if (isr & ADC_ISR_AWD3) { + /* Analog watchdog 3 error.*/ + emask |= ADC_ERR_AWD3; + } + if (emask != 0U) { + _adc_isr_error_code(adcp, emask); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (STM32_ADC_USE_ADC12 == TRUE) || defined(__DOXYGEN__) +/** + * @brief ADC1/ADC2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC12_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + /* Handle ADC1 ISR first in adc_lld_serve_interrupt. */ + isr = ADC1->ISR; + ADC1->ISR = isr; +#if defined(STM32_ADC_ADC12_IRQ_HOOK) + STM32_ADC_ADC12_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD1, isr); + + /* Handle ADC2 ISR next in adc_lld_serve_interrupt. */ +#if STM32_ADC_DUAL_MODE + isr |= ADC2->ISR; + ADC2->ISR = isr; +#if defined(STM32_ADC_ADC12_IRQ_HOOK) + STM32_ADC_ADC12_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD1, isr); +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + +#if (STM32_ADC_USE_ADC3 == TRUE) || defined(__DOXYGEN__) +/** + * @brief ADC3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC3_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC3->ISR; + ADC3->ISR = isr; +#if defined(STM32_ADC_ADC3_IRQ_HOOK) + STM32_ADC_ADC3_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD3, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_ADC3 == TRUE */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC12 == TRUE + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adcc = ADC12_COMMON; + ADCD1.adcm = ADC1; +#if STM32_ADC_DUAL_MODE + ADCD1.adcs = ADC2; +#endif + ADCD1.data.dma = NULL; + ADCD1.dmamode = ADC12_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + nvicEnableVector(STM32_ADC12_NUMBER, STM32_ADC_ADC12_IRQ_PRIORITY); +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + +#if STM32_ADC_USE_ADC3 == TRUE + /* Driver initialization.*/ + adcObjectInit(&ADCD3); + ADCD3.adcc = ADC3_COMMON; + ADCD3.adcm = ADC3; + ADCD3.data.bdma = NULL; + ADCD3.dmamode = ADC3_BDMA_SIZE | + STM32_BDMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | + STM32_BDMA_CR_DIR_P2M | + STM32_BDMA_CR_MINC | STM32_BDMA_CR_TCIE | + STM32_BDMA_CR_TEIE; + nvicEnableVector(STM32_ADC3_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY); +#endif /* STM32_ADC_USE_ADC3 == TRUE */ + + /* ADC units pre-initializations.*/ +#if (STM32_HAS_ADC1 == TRUE) && (STM32_HAS_ADC2 == TRUE) +#if STM32_ADC_USE_ADC12 == TRUE + rccEnableADC12(true); + rccResetADC12(); + ADC12_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF | ADC12_CCR_DUAL; + rccDisableADC12(); +#endif +#if STM32_ADC_USE_ADC3 == TRUE + rccEnableADC3(true); + rccResetADC3(); + ADC3_COMMON->CCR = STM32_ADC_ADC3_CLOCK_MODE; + rccDisableADC3(); +#endif +#endif +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* Handling the default configuration.*/ + if (adcp->config == NULL) { + adcp->config = &default_config; + } + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC12 == TRUE + if (&ADCD1 == adcp) { + adcp->data.dma = dmaStreamAllocI(STM32_ADC_ADC12_DMA_STREAM, + STM32_ADC_ADC12_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->data.dma != NULL, "unable to allocate stream"); + rccEnableADC12(true); + dmaSetRequestSource(adcp->data.dma, STM32_DMAMUX1_ADC1); + + /* Setting DMA peripheral-side pointer.*/ +#if STM32_ADC_DUAL_MODE + dmaStreamSetPeripheral(adcp->data.dma, &adcp->adcc->CDR); +#else + dmaStreamSetPeripheral(adcp->data.dma, &adcp->adcm->DR); +#endif + + /* Differential channels setting.*/ +#if STM32_ADC_DUAL_MODE + adcp->adcm->DIFSEL = adcp->config->difsel; + adcp->adcs->DIFSEL = adcp->config->difsel; +#else + adcp->adcm->DIFSEL = adcp->config->difsel; +#endif + } +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + +#if STM32_ADC_USE_ADC3 == TRUE + if (&ADCD3 == adcp) { + adcp->data.bdma = bdmaStreamAllocI(STM32_ADC_ADC3_BDMA_STREAM, + STM32_ADC_ADC3_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_bdma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->data.bdma != NULL, "unable to allocate stream"); + rccEnableADC3(true); + bdmaSetRequestSource(adcp->data.bdma, STM32_DMAMUX2_ADC3_REQ); + + /* Setting DMA peripheral-side pointer.*/ + bdmaStreamSetPeripheral(adcp->data.bdma, &adcp->adcm->DR); + + /* Differential channels setting.*/ + adcp->adcm->DIFSEL = adcp->config->difsel; + } +#endif /* STM32_ADC_USE_ADC3 == TRUE */ + + /* Master ADC calibration.*/ + adc_lld_vreg_on(adcp); + adc_lld_calibrate(adcp); + + /* Configure the ADC boost. */ +#if STM32_ADC_USE_ADC12 == TRUE + if (&ADCD1 == adcp) { + adcp->adcm->CR |= STM32_ADC12_BOOST; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR |= STM32_ADC12_BOOST; +#endif + } +#endif + +#if STM32_ADC_USE_ADC3 == TRUE + if (&ADCD3 == adcp) { + adcp->adcm->CR |= STM32_ADC3_BOOST; + } +#endif + + /* Master ADC enabled here in order to reduce conversions latencies.*/ + adc_lld_analog_on(adcp); + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + + /* Stopping the ongoing conversion, if any.*/ + adc_lld_stop_adc(adcp); + + /* Disabling ADC analog circuit and regulator.*/ + adc_lld_analog_off(adcp); + adc_lld_vreg_off(adcp); + +#if STM32_ADC_USE_ADC12 == TRUE + if (&ADCD1 == adcp) { + + /* Releasing the associated DMA channel.*/ + dmaStreamFreeI(adcp->data.dma); + adcp->data.dma = NULL; + + /* Resetting CCR options except default ones.*/ + adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF | ADC12_CCR_DUAL; + rccDisableADC12(); + } +#endif + +#if STM32_ADC_USE_ADC3 == TRUE + if (&ADCD3 == adcp) { + + /* Releasing the associated BDMA channel.*/ + bdmaStreamFreeI(adcp->data.bdma); + adcp->data.bdma = NULL; + + /* Resetting CCR options except default ones.*/ + adcp->adcc->CCR = STM32_ADC_ADC3_CLOCK_MODE; + rccDisableADC3(); + } +#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 dmamode, cfgr = 0U; + const ADCConversionGroup *grpp = adcp->grpp; + +#if STM32_ADC_USE_ADC12 == TRUE +#if STM32_ADC_DUAL_MODE + uint32_t ccr; +#endif + if (&ADCD1 == adcp) { +#if STM32_ADC_DUAL_MODE + ccr = grpp->ccr & ~(ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK); + osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0), + "odd number of channels in dual mode"); +#endif + + /* Calculating control registers values.*/ + dmamode = adcp->dmamode; + if (grpp->circular) { + dmamode |= STM32_DMA_CR_CIRC; + cfgr = grpp->cfgr | ADC_CFGR_DMNGT_CIRCULAR; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + dmamode |= STM32_DMA_CR_HTIE; + } + } + else { + cfgr = grpp->cfgr | ADC_CFGR_DMNGT_ONESHOT; + } + + /* DMA setup.*/ + dmaStreamSetMemory0(adcp->data.dma, adcp->samples); +#if STM32_ADC_DUAL_MODE + dmaStreamSetTransactionSize(adcp->data.dma, ((uint32_t)grpp->num_channels / 2U) * + (uint32_t)adcp->depth); +#else + dmaStreamSetTransactionSize(adcp->data.dma, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); +#endif + dmaStreamSetMode(adcp->data.dma, dmamode); + dmaStreamEnable(adcp->data.dma); + } +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + +#if STM32_ADC_USE_ADC3 == TRUE + if (&ADCD3 == adcp) { + /* Calculating control registers values.*/ + dmamode = adcp->dmamode; + if (grpp->circular) { + dmamode |= STM32_BDMA_CR_CIRC; + cfgr = grpp->cfgr | ADC_CFGR_DMNGT_CIRCULAR; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + dmamode |= STM32_BDMA_CR_HTIE; + } + } + else { + cfgr = grpp->cfgr | ADC_CFGR_DMNGT_ONESHOT; + } + + /* DMA setup.*/ + bdmaStreamSetMemory(adcp->data.bdma, adcp->samples); + bdmaStreamSetTransactionSize(adcp->data.bdma, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + bdmaStreamSetMode(adcp->data.bdma, dmamode); + bdmaStreamEnable(adcp->data.bdma); + } +#endif /* STM32_ADC_USE_ADC3 == TRUE */ + + /* ADC setup, if it is defined a callback for the analog watch dog then it + is enabled.*/ + /* clear AWD1..3 flags */ + adcp->adcm->ISR = adcp->adcm->ISR; + /* If a callback is set enable the overflow and analog watch dog interrupts. */ + if (grpp->error_cb != NULL) { + adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE + | ADC_IER_AWD2IE + | ADC_IER_AWD3IE; + } +#if STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE + /* Configuration for dual mode ADC12 */ + if (&ADCD1 == adcp) { + /* clear AWD1..3 flags */ + adcp->adcs->ISR = adcp->adcs->ISR; + /* If a callback is set enable the overflow and analog watch dog interrupts. */ + if (grpp->error_cb != NULL) { + adcp->adcs->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE + | ADC_IER_AWD2IE + | ADC_IER_AWD3IE; + /* Configuring the CCR register with the user-specified settings + in the conversion group configuration structure, static settings are + preserved.*/ + adcp->adcc->CCR = (adcp->adcc->CCR & + (ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK | ADC_CCR_DUAL_MASK)) | ccr; + + adcp->adcm->CFGR2 = grpp->cfgr2; + adcp->adcm->PCSEL = grpp->pcsel; + adcp->adcm->LTR1 = grpp->ltr1; + adcp->adcm->HTR1 = grpp->htr1; + adcp->adcm->LTR2 = grpp->ltr2; + adcp->adcm->HTR2 = grpp->htr2; + adcp->adcm->LTR3 = grpp->ltr3; + adcp->adcm->HTR3 = grpp->htr3; + adcp->adcm->AWD2CR = grpp->awd2cr; + adcp->adcm->AWD3CR = grpp->awd3cr; + adcp->adcm->SMPR1 = grpp->smpr[0]; + adcp->adcm->SMPR2 = grpp->smpr[1]; + adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); + adcp->adcm->SQR2 = grpp->sqr[1]; + adcp->adcm->SQR3 = grpp->sqr[2]; + adcp->adcm->SQR4 = grpp->sqr[3]; + adcp->adcs->CFGR2 = grpp->cfgr2; + adcp->adcs->PCSEL = grpp->pcsel; + adcp->adcs->LTR1 = grpp->sltr1; + adcp->adcs->HTR1 = grpp->shtr1; + adcp->adcs->LTR2 = grpp->sltr2; + adcp->adcs->HTR2 = grpp->shtr2; + adcp->adcs->LTR3 = grpp->sltr3; + adcp->adcs->HTR3 = grpp->shtr3; + adcp->adcs->AWD2CR = grpp->sawd2cr; + adcp->adcs->AWD3CR = grpp->sawd3cr; + adcp->adcs->SMPR1 = grpp->ssmpr[0]; + adcp->adcs->SMPR2 = grpp->ssmpr[1]; + adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); + adcp->adcs->SQR2 = grpp->ssqr[1]; + adcp->adcs->SQR3 = grpp->ssqr[2]; + adcp->adcs->SQR4 = grpp->ssqr[3]; + + /* ADC configuration.*/ + adcp->adcm->CFGR = cfgr; + adcp->adcs->CFGR = cfgr; + } +} +#endif /* STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE */ + +#if STM32_ADC_DUAL_MODE == FALSE || STM32_ADC_USE_ADC3 == TRUE + /* Configuration for ADC3 and single mode ADC1 */ + + adcp->adcm->CFGR2 = grpp->cfgr2; + adcp->adcm->PCSEL = grpp->pcsel; + adcp->adcm->LTR1 = grpp->ltr1; + adcp->adcm->HTR1 = grpp->htr1; + adcp->adcm->LTR2 = grpp->ltr2; + adcp->adcm->HTR2 = grpp->htr2; + adcp->adcm->LTR3 = grpp->ltr3; + adcp->adcm->HTR3 = grpp->htr3; + adcp->adcm->AWD2CR = grpp->awd2cr; + adcp->adcm->AWD3CR = grpp->awd3cr; + adcp->adcm->SMPR1 = grpp->smpr[0]; + adcp->adcm->SMPR2 = grpp->smpr[1]; + adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); + adcp->adcm->SQR2 = grpp->sqr[1]; + adcp->adcm->SQR3 = grpp->sqr[2]; + adcp->adcm->SQR4 = grpp->sqr[3]; + + /* ADC configuration.*/ + adcp->adcm->CFGR = cfgr; +#endif + + /* Starting conversion.*/ + adcp->adcm->CR |= ADC_CR_ADSTART; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + +#if STM32_ADC_USE_ADC12 == TRUE + if (&ADCD1 == adcp) { + dmaStreamDisable(adcp->data.dma); + } +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + +#if STM32_ADC_USE_ADC3 == TRUE + if (&ADCD3 == adcp) { + bdmaStreamDisable(adcp->data.bdma); + } +#endif /* STM32_ADC_USE_ADC12 == TRUE */ + + adc_lld_stop_adc(adcp); +} + +/** + * @brief Enables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVREF(ADCDriver *adcp) { + + adcp->adcc->CCR |= ADC_CCR_VREFEN; +} + +/** + * @brief Disables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVREF(ADCDriver *adcp) { + + adcp->adcc->CCR &= ~ADC_CCR_VREFEN; +} + +/** + * @brief Enables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableTS(ADCDriver *adcp) { + + adcp->adcc->CCR |= ADC_CCR_TSEN; +} + +/** + * @brief Disables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableTS(ADCDriver *adcp) { + + adcp->adcc->CCR &= ~ADC_CCR_TSEN; +} + +/** + * @brief Enables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVBAT(ADCDriver *adcp) { + + adcp->adcc->CCR |= ADC_CCR_VBATEN; +} + +/** + * @brief Disables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVBAT(ADCDriver *adcp) { + + adcp->adcc->CCR &= ~ADC_CCR_VBATEN; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h index 433f5fbf29..e3f35d208e 100644 --- a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h +++ b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h @@ -1,777 +1,777 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv4/hal_adc_lld.h - * @brief STM32 ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Possible ADC errors mask bits. - * @{ - */ -#define ADC_ERR_DMAFAILURE 1U /**< DMA operations failure. */ -#define ADC_ERR_OVERFLOW 2U /**< ADC overflow condition. */ -#define ADC_ERR_AWD1 4U /**< Watchdog 1 triggered. */ -#define ADC_ERR_AWD2 8U /**< Watchdog 2 triggered. */ -#define ADC_ERR_AWD3 16U /**< Watchdog 3 triggered. */ -/** @} */ - -/** - * @name Available analog channels - * @{ - */ -#define ADC_CHANNEL_IN0 0U /**< @brief External analog input 0. */ -#define ADC_CHANNEL_IN1 1U /**< @brief External analog input 1. */ -#define ADC_CHANNEL_IN2 2U /**< @brief External analog input 2. */ -#define ADC_CHANNEL_IN3 3U /**< @brief External analog input 3. */ -#define ADC_CHANNEL_IN4 4U /**< @brief External analog input 4. */ -#define ADC_CHANNEL_IN5 5U /**< @brief External analog input 5. */ -#define ADC_CHANNEL_IN6 6U /**< @brief External analog input 6. */ -#define ADC_CHANNEL_IN7 7U /**< @brief External analog input 7. */ -#define ADC_CHANNEL_IN8 8U /**< @brief External analog input 8. */ -#define ADC_CHANNEL_IN9 9U /**< @brief External analog input 9. */ -#define ADC_CHANNEL_IN10 10U /**< @brief External analog input 10. */ -#define ADC_CHANNEL_IN11 11U /**< @brief External analog input 11. */ -#define ADC_CHANNEL_IN12 12U /**< @brief External analog input 12. */ -#define ADC_CHANNEL_IN13 13U /**< @brief External analog input 13. */ -#define ADC_CHANNEL_IN14 14U /**< @brief External analog input 14. */ -#define ADC_CHANNEL_IN15 15U /**< @brief External analog input 15. */ -#define ADC_CHANNEL_IN16 16U /**< @brief External analog input 16. */ -#define ADC_CHANNEL_IN17 17U /**< @brief External analog input 17. */ -#define ADC_CHANNEL_IN18 18U /**< @brief External analog input 18. */ -#define ADC_CHANNEL_IN19 19U /**< @brief External analog input 19. */ -/** @} */ - -/** - * @name ADC channels selection masks - * @{ - */ -#define ADC_SELMASK_IN0 (1U << ADC_CHANNEL_IN0) -#define ADC_SELMASK_IN1 (1U << ADC_CHANNEL_IN1) -#define ADC_SELMASK_IN2 (1U << ADC_CHANNEL_IN2) -#define ADC_SELMASK_IN3 (1U << ADC_CHANNEL_IN3) -#define ADC_SELMASK_IN4 (1U << ADC_CHANNEL_IN4) -#define ADC_SELMASK_IN5 (1U << ADC_CHANNEL_IN5) -#define ADC_SELMASK_IN6 (1U << ADC_CHANNEL_IN6) -#define ADC_SELMASK_IN7 (1U << ADC_CHANNEL_IN7) -#define ADC_SELMASK_IN8 (1U << ADC_CHANNEL_IN8) -#define ADC_SELMASK_IN9 (1U << ADC_CHANNEL_IN9) -#define ADC_SELMASK_IN10 (1U << ADC_CHANNEL_IN10) -#define ADC_SELMASK_IN11 (1U << ADC_CHANNEL_IN11) -#define ADC_SELMASK_IN12 (1U << ADC_CHANNEL_IN12) -#define ADC_SELMASK_IN13 (1U << ADC_CHANNEL_IN13) -#define ADC_SELMASK_IN14 (1U << ADC_CHANNEL_IN14) -#define ADC_SELMASK_IN15 (1U << ADC_CHANNEL_IN15) -#define ADC_SELMASK_IN16 (1U << ADC_CHANNEL_IN16) -#define ADC_SELMASK_IN17 (1U << ADC_CHANNEL_IN17) -#define ADC_SELMASK_IN18 (1U << ADC_CHANNEL_IN18) -#define ADC_SELMASK_IN19 (1U << ADC_CHANNEL_IN19) -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#if defined(STM32H7XX) -#define ADC_SMPR_SMP_1P5 0U /**< @brief 9 cycles conversion time */ -#define ADC_SMPR_SMP_2P5 1U /**< @brief 10 cycles conversion time. */ -#define ADC_SMPR_SMP_8P5 2U /**< @brief 16 cycles conversion time. */ -#define ADC_SMPR_SMP_16P5 3U /**< @brief 24 cycles conversion time. */ -#define ADC_SMPR_SMP_32P5 4U /**< @brief 40 cycles conversion time. */ -#define ADC_SMPR_SMP_64P5 5U /**< @brief 72 cycles conversion time. */ -#define ADC_SMPR_SMP_384P5 6U /**< @brief 392 cycles conversion time. */ -#define ADC_SMPR_SMP_810P5 7U /**< @brief 818 cycles conversion time. */ -#endif -/** @} */ - -/** - * @name CFGR register configuration helpers - * @{ - */ -#define ADC_CFGR_DMNGT_MASK (3U << 0U) -#define ADC_CFGR_DMNGT_NODMA (0U << 0U) -#define ADC_CFGR_DMNGT_ONESHOT (1U << 0U) -#define ADC_CFGR_DMNGT_DFSDM (2U << 0U) -#define ADC_CFGR_DMNGT_CIRCULAR (3U << 0U) - -#define ADC_CFGR_RES_MASK (7U << 2U) -#define ADC_CFGR_RES_16BITS (0U << 2U) -#define ADC_CFGR_RES_10BITS (3U << 2U) -#if !defined(STM32_ENFORCE_H7_REV_XY) -#define ADC_CFGR_RES_14BITS (5U << 2U) -#define ADC_CFGR_RES_12BITS (6U << 2U) -#define ADC_CFGR_RES_8BITS (7U << 2U) -#else -#define ADC_CFGR_RES_14BITS (1U << 2U) -#define ADC_CFGR_RES_12BITS (2U << 2U) -#define ADC_CFGR_RES_8BITS (4U << 2U) -#endif - -#define ADC_CFGR_EXTSEL_MASK (15U << 5U) -#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 5U) - -#define ADC_CFGR_EXTEN_MASK (3U << 10U) -#define ADC_CFGR_EXTEN_DISABLED (0U << 10U) -#define ADC_CFGR_EXTEN_RISING (1U << 10U) -#define ADC_CFGR_EXTEN_FALLING (2U << 10U) -#define ADC_CFGR_EXTEN_BOTH (3U << 10U) - -#define ADC_CFGR_CONT_MASK (1U << 13U) -#define ADC_CFGR_CONT_DISABLED (0U << 13U) -#define ADC_CFGR_CONT_ENABLED (1U << 13U) - -#define ADC_CFGR_DISCEN_MASK (1U << 16U) -#define ADC_CFGR_DISCEN_DISABLED (0U << 16U) -#define ADC_CFGR_DISCEN_ENABLED (1U << 16U) - -#define ADC_CFGR_DISCNUM_MASK (7U << 17U) -#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17U) -/** @} */ - -/** - * @name CCR register configuration helpers - * @{ - */ -#define ADC_CCR_DUAL_MASK (31U << 0U) -#define ADC_CCR_DUAL_FIELD(n) ((n) << 0U) -#define ADC_CCR_DUAL_INDEPENDENT (0U << 0U) /**< @brief Independent, dual mode disabled. */ -#define ADC_CCR_DUAL_REG_SIMULT (6U << 0U) /**< @brief Regular simultaneous. */ -#define ADC_CCR_DUAL_REG_INTERL (7U << 0U) /**< @brief Regular interleaved. */ -#define ADC_CCR_DUAL_INJ_SIMULT (5U << 0U) /**< @brief Injected simultaneous. */ -#define ADC_CCR_DUAL_INJ_ALTERNATE (9U << 0U) /**< @brief Injected alternate trigger. */ -#define ADC_CCR_DUAL_REG_SIM_INJ_SIM (1U << 0U) /**< @brief Combined regular simultaneous + injected simultaneous. */ -#define ADC_CCR_DUAL_REG_SIM_INJ_ALT (2U << 0U) /**< @brief Combined regular simultaneous + injected alternate trigger. */ -#define ADC_CCR_DUAL_REG_INT_INJ_SIM (3U << 0U) /**< @brief Combined regular interleaved + injected simultaneous. */ -#define ADC_CCR_DELAY_MASK (15U << 8U) -#define ADC_CCR_DELAY_FIELD(n) ((n) << 8U) -#define ADC_CCR_DAMDF_MASK (3U << 14U) -#define ADC_CCR_DAMDF_DISABLED (0U << 14U) -#define ADC_CCR_DAMDF_HWORD (2U << 14U) -#define ADC_CCR_DAMDF_BYTE (3U << 14U) -#define ADC_CCR_CKMODE_MASK (3U << 16U) -#define ADC_CCR_CKMODE_ADCCK (0U << 16U) -#define ADC_CCR_CKMODE_AHB_DIV1 (1U << 16U) -#define ADC_CCR_CKMODE_AHB_DIV2 (2U << 16U) -#define ADC_CCR_CKMODE_AHB_DIV4 (3U << 16U) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Enables the ADC1 and ADC2 master/slave mode. - */ -#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_DUAL_MODE FALSE -#endif - -/** - * @brief Specifies the ADC samples width. - * @note Must be 8, 16 or 32. - * @note 10, 12, 14 and 16 bits sampling modes must not be used when - * this option is set to 8. - * @note 32 is useful when oversampling is activated. - */ -#if !defined(STM32_ADC_SAMPLES_SIZE) || defined(__DOXYGEN__) -#define STM32_ADC_SAMPLES_SIZE 16 -#endif - -/** - * @brief ADC1/ADC2 driver enable switch. - * @details If set to @p TRUE the support for ADC1/ADC2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC12) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC12 FALSE -#endif - -/** - * @brief ADC3 driver enable switch. - * @details If set to @p TRUE the support for ADC3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC3 FALSE -#endif - -/** - * @brief ADC1/ADC2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC12_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_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 ADC1/ADC2 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC3 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC1/ADC2 clock source and mode. - */ -#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#endif - -/** - * @brief ADC3 clock source and mode. - */ -#if !defined(STM32_ADC_ADC3_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Supported devices checks.*/ -#if !defined(STM32H7XX) -#error "ADCv4 only supports H7 STM32 devices" -#endif - -/* Registry checks.*/ -#if !defined(STM32_HAS_ADC1) || !defined(STM32_HAS_ADC2) || \ - !defined(STM32_HAS_ADC3) -#error "STM32_HAS_ADCx not defined in registry" -#endif - -/* Units checks.*/ -#if STM32_ADC_USE_ADC12 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if STM32_ADC_DUAL_MODE && !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 - -/* IRQ handlers checks.*/ -#if STM32_HAS_ADC1 && !defined(STM32_ADC12_HANDLER) -#error "STM32_ADC12_HANDLER not defined in registry" -#endif - -#if STM32_HAS_ADC2 && !defined(STM32_ADC12_HANDLER) -#error "STM32_ADC12_HANDLER not defined in registry" -#endif - -#if STM32_HAS_ADC3 && !defined(STM32_ADC3_HANDLER) -#error "STM32_ADC3_HANDLER not defined in registry" -#endif - -/* IRQ vector numbers checks.*/ -#if STM32_HAS_ADC1 && !defined(STM32_ADC12_NUMBER) -#error "STM32_ADC12_NUMBER not defined in registry" -#endif - -#if STM32_HAS_ADC2 && !defined(STM32_ADC12_NUMBER) -#error "STM32_ADC12_NUMBER not defined in registry" -#endif - -#if STM32_HAS_ADC3 && !defined(STM32_ADC3_NUMBER) -#error "STM32_ADC3_NUMBER not defined in registry" -#endif - -/* At least one ADC must be assigned.*/ -#if !STM32_ADC_USE_ADC12 && !STM32_ADC_USE_ADC3 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -/* Dual mode is only supported with ADC12.*/ -#if !STM32_ADC_USE_ADC12 && STM32_ADC_DUAL_MODE -#error "STM32_ADC_DUAL_MODE only supported with ADC12" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_ADC_USE_ADC12 && !defined(STM32_ADC_ADC12_DMA_STREAM) -#error "STM32_ADC_ADC12_DMA_STREAM not defined" -#endif - -#if STM32_ADC_USE_ADC3 && !defined(STM32_ADC_ADC3_BDMA_STREAM) -#error "STM32_ADC_ADC3_BDMA_STREAM not defined" -#endif - -/* DMA channel range tests.*/ -#if STM32_ADC_USE_ADC12 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_ADC_ADC12_DMA_STREAM) -#error "Invalid DMA channel assigned to ADC12" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !STM32_BDMA_IS_VALID_STREAM(STM32_ADC_ADC3_BDMA_STREAM) -#error "Invalid DMA channel assigned to ADC3" -#endif - -/* DMA priority tests.*/ -#if STM32_ADC_USE_ADC12 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC12_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC3" -#endif - -/* ADC IRQ priority tests.*/ -#if STM32_ADC_USE_ADC12 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC3" -#endif - -#if ((STM32_ADC_SAMPLES_SIZE != 8) && \ - (STM32_ADC_SAMPLES_SIZE != 16) && \ - (STM32_ADC_SAMPLES_SIZE != 32)) -#error "STM32_ADC_SAMPLES_SIZE must be 8, 16 or 32" -#endif - -#if (STM32_ADC_SAMPLES_SIZE != 32) && STM32_ADC_DUAL_MODE -#error "STM32_ADC_SAMPLES_SIZE = 32 not compatible with STM32_ADC_DUAL_MODE" -#endif - -#if !defined(STM32_ENFORCE_H7_REV_XY) -/* ADC clock source checks.*/ -#if (STM32_D1HPRE == STM32_D1HPRE_DIV1) -#define STM32_ADC_SCLK STM32_HCLK -#else -#define STM32_ADC_SCLK (STM32_HCLK / 2) -#endif - -#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -/* CHTODO: also check ADC_CCR_PRESC.*/ -#define STM32_ADC12_CLOCK (STM32_ADCCLK / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 1 / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 2 / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 4 / 2) -#else -#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" -#endif - -#if STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -/* CHTODO: also check ADC_CCR_PRESC.*/ -#define STM32_ADC3_CLOCK (STM32_ADCCLK / 2) -#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 1 / 2) -#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 2 / 2) -#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 4 / 2) -#else -#error "invalid clock mode selected for STM32_ADC_ADC3_CLOCK_MODE" -#endif - -#else /* defined(STM32_ENFORCE_H7_REV_XY) */ - -#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC12_CLOCK STM32_ADCCLK -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC12_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC12_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC12_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" -#endif - -#if STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC3_CLOCK STM32_ADCCLK -#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC3_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC3_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC3_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC3_CLOCK_MODE" -#endif - -#endif /* defined(STM32_ENFORCE_H7_REV_XY) */ - -#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -#if STM32_ADC3_CLOCK > STM32_ADCCLK_MAX -#error "STM32_ADC3_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -#if !defined(STM32_ENFORCE_H7_REV_XY) -/* ADC boost checks.*/ -#if STM32_ADC12_CLOCK > 6250000 -#define STM32_ADC12_BOOST (1U << 8U) -#elif STM32_ADC12_CLOCK > 12500000 -#define STM32_ADC12_BOOST (2U << 8U) -#elif STM32_ADC12_CLOCK > 25000000 -#define STM32_ADC12_BOOST (3U << 8U) -#else -#define STM32_ADC12_BOOST (0U << 8U) -#endif - -#if STM32_ADC3_CLOCK > 6250000 -#define STM32_ADC3_BOOST (1U << 8U) -#elif STM32_ADC3_CLOCK > 12500000 -#define STM32_ADC3_BOOST (2U << 8U) -#elif STM32_ADC3_CLOCK > 25000000 -#define STM32_ADC3_BOOST (3U << 8U) -#else -#define STM32_ADC3_BOOST (0U << 8U) -#endif - -#else /* defined(STM32_ENFORCE_H7_REV_XY) */ - -#if STM32_ADC12_CLOCK > 20000000 -#define STM32_ADC12_BOOST (1U << 8U) -#else -#define STM32_ADC12_BOOST (0U << 8U) -#endif - -#if STM32_ADC3_CLOCK > 20000000 -#define STM32_ADC3_BOOST (1U << 8U) -#else -#define STM32_ADC3_BOOST (0U << 8U) -#endif - -#endif /* defined(STM32_ENFORCE_H7_REV_XY) */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -#if STM32_ADC_USE_ADC12 -#define STM32_ADC_DMA_REQUIRED -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif -#endif - -#if STM32_ADC_USE_ADC3 -#define STM32_ADC_BDMA_REQUIRED -#if !defined(STM32_BDMA_REQUIRED) -#define STM32_BDMA_REQUIRED -#endif -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -#if (STM32_ADC_SAMPLES_SIZE == 16) || defined(__DOXYGEN__) -typedef uint16_t adcsample_t; -#elif (STM32_ADC_SAMPLES_SIZE == 8) -typedef uint8_t adcsample_t; -#elif (STM32_ADC_SAMPLES_SIZE == 32) -typedef uint32_t adcsample_t; -#endif - -/** - * @brief Channels number in a conversion group. - */ -typedef uint32_t adc_channels_num_t; - -/** - * @brief Type of an ADC error mask. - */ -typedef uint32_t adcerror_t; - -/** - * @brief Type of a DMA channel pointer choice. - */ -typedef union { -#if defined(STM32_ADC_DMA_REQUIRED) || defined(__DOXYGEN__) - /** - * @brief DMA stream. - */ - const stm32_dma_stream_t *dma; -#endif -#if defined(STM32_ADC_BDMA_REQUIRED) || defined(__DOXYGEN__) - /** - * @brief BDMA stream. - */ - const stm32_bdma_stream_t *bdma; -#endif -} adc_ldd_dma_reference_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) -#define adc_lld_driver_fields \ - /* Pointer to the master ADCx registers block.*/ \ - ADC_TypeDef *adcm; \ - /* Pointer to the slave ADCx registers block.*/ \ - ADC_TypeDef *adcs; \ - /* Pointer to the common ADCx_y registers block.*/ \ - ADC_Common_TypeDef *adcc; \ - /* Pointer to associated DMA channel.*/ \ - adc_ldd_dma_reference_t data; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode -#else -#define adc_lld_driver_fields \ - /* Pointer to the master ADCx registers block.*/ \ - ADC_TypeDef *adcm; \ - /* Pointer to the slave ADCx registers block.*/ \ - ADC_Common_TypeDef *adcc; \ - /* Pointer to associated DMA channel.*/ \ - adc_ldd_dma_reference_t data; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode -#endif - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* ADC DIFSEL register initialization data.*/ \ - uint32_t difsel; \ - /* Calibration mode, specify ADCCALIN and/or ADCCALDIF bits in here.*/ \ - uint32_t calibration - -#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) -#define adc_lld_configuration_group_fields \ - /* ADC CFGR register initialization data. \ - NOTE: The bits DMAEN and DMACFG are enforced internally \ - to the driver, keep them to zero. \ - NOTE: The bits @p ADC_CFGR_CONT or @p ADC_CFGR_DISCEN must be \ - specified in continuous mode or if the buffer depth is \ - greater than one.*/ \ - uint32_t cfgr; \ - /* ADC CFGR2 register initialization data. \ - NOTE: Put this field to zero if not using oversampling.*/ \ - uint32_t cfgr2; \ - /* ADC CCR register initialization data*/ \ - uint32_t ccr; \ - /* ADC PCSEL register initialization data.*/ \ - uint32_t pcsel; \ - /* ADC LTR1 register initialization data.*/ \ - uint32_t ltr1; \ - /* ADC HTR1 register initialization data.*/ \ - uint32_t htr1; \ - /* ADC LTR2 register initialization data.*/ \ - uint32_t ltr2; \ - /* ADC HTR2 register initialization data.*/ \ - uint32_t htr2; \ - /* ADC LTR3 register initialization data.*/ \ - uint32_t ltr3; \ - /* ADC HTR3 register initialization data.*/ \ - uint32_t htr3; \ - /* ADC AWD2CR register initialization data.*/ \ - uint32_t awd2cr; \ - /* ADC AWD3CR register initialization data.*/ \ - uint32_t awd3cr; \ - /* ADC SMPRx registers initialization data.*/ \ - uint32_t smpr[2]; \ - /* ADC SQRx register initialization data.*/ \ - uint32_t sqr[4]; \ - /* Slave ADC LTR/HTRx registers initialization data. \ - NOTE: This field is only present in dual mode.*/ \ - uint32_t sltr1; \ - uint32_t shtr1; \ - uint32_t sltr2; \ - uint32_t shtr2; \ - uint32_t sltr3; \ - uint32_t shtr3; \ - /* Slave ADC AWDxCR registers initialization data. \ - NOTE: This field is only present in dual mode.*/ \ - uint32_t sawd2cr; \ - uint32_t sawd3cr; \ - /* Slave ADC SMPRx registers initialization data. \ - NOTE: This field is only present in dual mode.*/ \ - uint32_t ssmpr[2]; \ - /* Slave ADC SQRx register initialization data. \ - NOTE: This field is only present in dual mode.*/ \ - uint32_t ssqr[4] -#else /* STM32_ADC_DUAL_MODE == FALSE */ -#define adc_lld_configuration_group_fields \ - uint32_t cfgr; \ - uint32_t cfgr2; \ - uint32_t ccr; \ - uint32_t pcsel; \ - uint32_t ltr1; \ - uint32_t htr1; \ - uint32_t ltr2; \ - uint32_t htr2; \ - uint32_t ltr3; \ - uint32_t htr3; \ - uint32_t awd2cr; \ - uint32_t awd3cr; \ - uint32_t smpr[2]; \ - uint32_t sqr[4] -#endif /* STM32_ADC_DUAL_MODE == FALSE */ - -/** - * @name Sequences building helper macros - * @{ - */ -/** - * @brief Number of channels in a conversion sequence. - */ -#define ADC_SQR1_NUM_CH(n) (((n) - 1U) << 0U) - -#define ADC_SQR1_SQ1_N(n) ((n) << 6U) /**< @brief 1st channel in seq. */ -#define ADC_SQR1_SQ2_N(n) ((n) << 12U)/**< @brief 2nd channel in seq. */ -#define ADC_SQR1_SQ3_N(n) ((n) << 18U)/**< @brief 3rd channel in seq. */ -#define ADC_SQR1_SQ4_N(n) ((n) << 24U)/**< @brief 4th channel in seq. */ - -#define ADC_SQR2_SQ5_N(n) ((n) << 0U) /**< @brief 5th channel in seq. */ -#define ADC_SQR2_SQ6_N(n) ((n) << 6U) /**< @brief 6th channel in seq. */ -#define ADC_SQR2_SQ7_N(n) ((n) << 12U)/**< @brief 7th channel in seq. */ -#define ADC_SQR2_SQ8_N(n) ((n) << 18U)/**< @brief 8th channel in seq. */ -#define ADC_SQR2_SQ9_N(n) ((n) << 24U)/**< @brief 9th channel in seq. */ - -#define ADC_SQR3_SQ10_N(n) ((n) << 0U) /**< @brief 10th channel in seq.*/ -#define ADC_SQR3_SQ11_N(n) ((n) << 6U) /**< @brief 11th channel in seq.*/ -#define ADC_SQR3_SQ12_N(n) ((n) << 12U)/**< @brief 12th channel in seq.*/ -#define ADC_SQR3_SQ13_N(n) ((n) << 18U)/**< @brief 13th channel in seq.*/ -#define ADC_SQR3_SQ14_N(n) ((n) << 24U)/**< @brief 14th channel in seq.*/ - -#define ADC_SQR4_SQ15_N(n) ((n) << 0U) /**< @brief 15th channel in seq.*/ -#define ADC_SQR4_SQ16_N(n) ((n) << 6U) /**< @brief 16th channel in seq.*/ -/** @} */ - -/** - * @name Sampling rate settings helper macros - * @{ - */ -#define ADC_SMPR1_SMP_AN0(n) ((n) << 0U) /**< @brief AN0 sampling time. */ -#define ADC_SMPR1_SMP_AN1(n) ((n) << 3U) /**< @brief AN1 sampling time. */ -#define ADC_SMPR1_SMP_AN2(n) ((n) << 6U) /**< @brief AN2 sampling time. */ -#define ADC_SMPR1_SMP_AN3(n) ((n) << 9U) /**< @brief AN3 sampling time. */ -#define ADC_SMPR1_SMP_AN4(n) ((n) << 12U)/**< @brief AN4 sampling time. */ -#define ADC_SMPR1_SMP_AN5(n) ((n) << 15U)/**< @brief AN5 sampling time. */ -#define ADC_SMPR1_SMP_AN6(n) ((n) << 18U)/**< @brief AN6 sampling time. */ -#define ADC_SMPR1_SMP_AN7(n) ((n) << 21U)/**< @brief AN7 sampling time. */ -#define ADC_SMPR1_SMP_AN8(n) ((n) << 24U)/**< @brief AN8 sampling time. */ -#define ADC_SMPR1_SMP_AN9(n) ((n) << 27U)/**< @brief AN9 sampling time. */ - -#define ADC_SMPR2_SMP_AN10(n) ((n) << 0U) /**< @brief AN10 sampling time. */ -#define ADC_SMPR2_SMP_AN11(n) ((n) << 3U) /**< @brief AN11 sampling time. */ -#define ADC_SMPR2_SMP_AN12(n) ((n) << 6U) /**< @brief AN12 sampling time. */ -#define ADC_SMPR2_SMP_AN13(n) ((n) << 9U) /**< @brief AN13 sampling time. */ -#define ADC_SMPR2_SMP_AN14(n) ((n) << 12U)/**< @brief AN14 sampling time. */ -#define ADC_SMPR2_SMP_AN15(n) ((n) << 15U)/**< @brief AN15 sampling time. */ -#define ADC_SMPR2_SMP_AN16(n) ((n) << 18U)/**< @brief AN16 sampling time. */ -#define ADC_SMPR2_SMP_AN17(n) ((n) << 21U)/**< @brief AN17 sampling time. */ -#define ADC_SMPR2_SMP_AN18(n) ((n) << 24U)/**< @brief AN18 sampling time. */ -#define ADC_SMPR2_SMP_AN19(n) ((n) << 27U)/**< @brief AN19 sampling time. */ -/** @} */ - -/** - * @name Analog watchdog settings helper macros - * @{ - */ -#define ADC_CFGR_AWD1_N(n) ((n) << 26U)/**< @brief AWD1 channel number */ -#define ADC_AWD23_MASK(n) (1U << (n)) /**< @brief AWD2/3 channels mask*/ -/** @} */ - -/** - * @name Oversampling settings helper macros - * @{ - */ -#define ADC_CFGR2_OVSS_N(n) ((n) << 5U)/**< @brief ovsr right shift */ -#define ADC_CFGR2_OVSR_N(n) ((n) << 16U)/**< @brief oversampling ratio */ -#define ADC_CFGR2_LSHIFT_N(n) ((n) << 28U)/**< @brief ovsr left shift */ - -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC12 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#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 adcSTM32EnableVREF(ADCDriver *adcp); - void adcSTM32DisableVREF(ADCDriver *adcp); - void adcSTM32EnableTS(ADCDriver *adcp); - void adcSTM32DisableTS(ADCDriver *adcp); - void adcSTM32EnableVBAT(ADCDriver *adcp); - void adcSTM32DisableVBAT(ADCDriver *adcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv4/hal_adc_lld.h + * @brief STM32 ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Possible ADC errors mask bits. + * @{ + */ +#define ADC_ERR_DMAFAILURE 1U /**< DMA operations failure. */ +#define ADC_ERR_OVERFLOW 2U /**< ADC overflow condition. */ +#define ADC_ERR_AWD1 4U /**< Watchdog 1 triggered. */ +#define ADC_ERR_AWD2 8U /**< Watchdog 2 triggered. */ +#define ADC_ERR_AWD3 16U /**< Watchdog 3 triggered. */ +/** @} */ + +/** + * @name Available analog channels + * @{ + */ +#define ADC_CHANNEL_IN0 0U /**< @brief External analog input 0. */ +#define ADC_CHANNEL_IN1 1U /**< @brief External analog input 1. */ +#define ADC_CHANNEL_IN2 2U /**< @brief External analog input 2. */ +#define ADC_CHANNEL_IN3 3U /**< @brief External analog input 3. */ +#define ADC_CHANNEL_IN4 4U /**< @brief External analog input 4. */ +#define ADC_CHANNEL_IN5 5U /**< @brief External analog input 5. */ +#define ADC_CHANNEL_IN6 6U /**< @brief External analog input 6. */ +#define ADC_CHANNEL_IN7 7U /**< @brief External analog input 7. */ +#define ADC_CHANNEL_IN8 8U /**< @brief External analog input 8. */ +#define ADC_CHANNEL_IN9 9U /**< @brief External analog input 9. */ +#define ADC_CHANNEL_IN10 10U /**< @brief External analog input 10. */ +#define ADC_CHANNEL_IN11 11U /**< @brief External analog input 11. */ +#define ADC_CHANNEL_IN12 12U /**< @brief External analog input 12. */ +#define ADC_CHANNEL_IN13 13U /**< @brief External analog input 13. */ +#define ADC_CHANNEL_IN14 14U /**< @brief External analog input 14. */ +#define ADC_CHANNEL_IN15 15U /**< @brief External analog input 15. */ +#define ADC_CHANNEL_IN16 16U /**< @brief External analog input 16. */ +#define ADC_CHANNEL_IN17 17U /**< @brief External analog input 17. */ +#define ADC_CHANNEL_IN18 18U /**< @brief External analog input 18. */ +#define ADC_CHANNEL_IN19 19U /**< @brief External analog input 19. */ +/** @} */ + +/** + * @name ADC channels selection masks + * @{ + */ +#define ADC_SELMASK_IN0 (1U << ADC_CHANNEL_IN0) +#define ADC_SELMASK_IN1 (1U << ADC_CHANNEL_IN1) +#define ADC_SELMASK_IN2 (1U << ADC_CHANNEL_IN2) +#define ADC_SELMASK_IN3 (1U << ADC_CHANNEL_IN3) +#define ADC_SELMASK_IN4 (1U << ADC_CHANNEL_IN4) +#define ADC_SELMASK_IN5 (1U << ADC_CHANNEL_IN5) +#define ADC_SELMASK_IN6 (1U << ADC_CHANNEL_IN6) +#define ADC_SELMASK_IN7 (1U << ADC_CHANNEL_IN7) +#define ADC_SELMASK_IN8 (1U << ADC_CHANNEL_IN8) +#define ADC_SELMASK_IN9 (1U << ADC_CHANNEL_IN9) +#define ADC_SELMASK_IN10 (1U << ADC_CHANNEL_IN10) +#define ADC_SELMASK_IN11 (1U << ADC_CHANNEL_IN11) +#define ADC_SELMASK_IN12 (1U << ADC_CHANNEL_IN12) +#define ADC_SELMASK_IN13 (1U << ADC_CHANNEL_IN13) +#define ADC_SELMASK_IN14 (1U << ADC_CHANNEL_IN14) +#define ADC_SELMASK_IN15 (1U << ADC_CHANNEL_IN15) +#define ADC_SELMASK_IN16 (1U << ADC_CHANNEL_IN16) +#define ADC_SELMASK_IN17 (1U << ADC_CHANNEL_IN17) +#define ADC_SELMASK_IN18 (1U << ADC_CHANNEL_IN18) +#define ADC_SELMASK_IN19 (1U << ADC_CHANNEL_IN19) +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#if defined(STM32H7XX) +#define ADC_SMPR_SMP_1P5 0U /**< @brief 9 cycles conversion time */ +#define ADC_SMPR_SMP_2P5 1U /**< @brief 10 cycles conversion time. */ +#define ADC_SMPR_SMP_8P5 2U /**< @brief 16 cycles conversion time. */ +#define ADC_SMPR_SMP_16P5 3U /**< @brief 24 cycles conversion time. */ +#define ADC_SMPR_SMP_32P5 4U /**< @brief 40 cycles conversion time. */ +#define ADC_SMPR_SMP_64P5 5U /**< @brief 72 cycles conversion time. */ +#define ADC_SMPR_SMP_384P5 6U /**< @brief 392 cycles conversion time. */ +#define ADC_SMPR_SMP_810P5 7U /**< @brief 818 cycles conversion time. */ +#endif +/** @} */ + +/** + * @name CFGR register configuration helpers + * @{ + */ +#define ADC_CFGR_DMNGT_MASK (3U << 0U) +#define ADC_CFGR_DMNGT_NODMA (0U << 0U) +#define ADC_CFGR_DMNGT_ONESHOT (1U << 0U) +#define ADC_CFGR_DMNGT_DFSDM (2U << 0U) +#define ADC_CFGR_DMNGT_CIRCULAR (3U << 0U) + +#define ADC_CFGR_RES_MASK (7U << 2U) +#define ADC_CFGR_RES_16BITS (0U << 2U) +#define ADC_CFGR_RES_10BITS (3U << 2U) +#if !defined(STM32_ENFORCE_H7_REV_XY) +#define ADC_CFGR_RES_14BITS (5U << 2U) +#define ADC_CFGR_RES_12BITS (6U << 2U) +#define ADC_CFGR_RES_8BITS (7U << 2U) +#else +#define ADC_CFGR_RES_14BITS (1U << 2U) +#define ADC_CFGR_RES_12BITS (2U << 2U) +#define ADC_CFGR_RES_8BITS (4U << 2U) +#endif + +#define ADC_CFGR_EXTSEL_MASK (15U << 5U) +#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 5U) + +#define ADC_CFGR_EXTEN_MASK (3U << 10U) +#define ADC_CFGR_EXTEN_DISABLED (0U << 10U) +#define ADC_CFGR_EXTEN_RISING (1U << 10U) +#define ADC_CFGR_EXTEN_FALLING (2U << 10U) +#define ADC_CFGR_EXTEN_BOTH (3U << 10U) + +#define ADC_CFGR_CONT_MASK (1U << 13U) +#define ADC_CFGR_CONT_DISABLED (0U << 13U) +#define ADC_CFGR_CONT_ENABLED (1U << 13U) + +#define ADC_CFGR_DISCEN_MASK (1U << 16U) +#define ADC_CFGR_DISCEN_DISABLED (0U << 16U) +#define ADC_CFGR_DISCEN_ENABLED (1U << 16U) + +#define ADC_CFGR_DISCNUM_MASK (7U << 17U) +#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17U) +/** @} */ + +/** + * @name CCR register configuration helpers + * @{ + */ +#define ADC_CCR_DUAL_MASK (31U << 0U) +#define ADC_CCR_DUAL_FIELD(n) ((n) << 0U) +#define ADC_CCR_DUAL_INDEPENDENT (0U << 0U) /**< @brief Independent, dual mode disabled. */ +#define ADC_CCR_DUAL_REG_SIMULT (6U << 0U) /**< @brief Regular simultaneous. */ +#define ADC_CCR_DUAL_REG_INTERL (7U << 0U) /**< @brief Regular interleaved. */ +#define ADC_CCR_DUAL_INJ_SIMULT (5U << 0U) /**< @brief Injected simultaneous. */ +#define ADC_CCR_DUAL_INJ_ALTERNATE (9U << 0U) /**< @brief Injected alternate trigger. */ +#define ADC_CCR_DUAL_REG_SIM_INJ_SIM (1U << 0U) /**< @brief Combined regular simultaneous + injected simultaneous. */ +#define ADC_CCR_DUAL_REG_SIM_INJ_ALT (2U << 0U) /**< @brief Combined regular simultaneous + injected alternate trigger. */ +#define ADC_CCR_DUAL_REG_INT_INJ_SIM (3U << 0U) /**< @brief Combined regular interleaved + injected simultaneous. */ +#define ADC_CCR_DELAY_MASK (15U << 8U) +#define ADC_CCR_DELAY_FIELD(n) ((n) << 8U) +#define ADC_CCR_DAMDF_MASK (3U << 14U) +#define ADC_CCR_DAMDF_DISABLED (0U << 14U) +#define ADC_CCR_DAMDF_HWORD (2U << 14U) +#define ADC_CCR_DAMDF_BYTE (3U << 14U) +#define ADC_CCR_CKMODE_MASK (3U << 16U) +#define ADC_CCR_CKMODE_ADCCK (0U << 16U) +#define ADC_CCR_CKMODE_AHB_DIV1 (1U << 16U) +#define ADC_CCR_CKMODE_AHB_DIV2 (2U << 16U) +#define ADC_CCR_CKMODE_AHB_DIV4 (3U << 16U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Enables the ADC1 and ADC2 master/slave mode. + */ +#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_DUAL_MODE FALSE +#endif + +/** + * @brief Specifies the ADC samples width. + * @note Must be 8, 16 or 32. + * @note 10, 12, 14 and 16 bits sampling modes must not be used when + * this option is set to 8. + * @note 32 is useful when oversampling is activated. + */ +#if !defined(STM32_ADC_SAMPLES_SIZE) || defined(__DOXYGEN__) +#define STM32_ADC_SAMPLES_SIZE 16 +#endif + +/** + * @brief ADC1/ADC2 driver enable switch. + * @details If set to @p TRUE the support for ADC1/ADC2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC12) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC12 FALSE +#endif + +/** + * @brief ADC3 driver enable switch. + * @details If set to @p TRUE the support for ADC3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC3 FALSE +#endif + +/** + * @brief ADC1/ADC2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC12_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_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 ADC1/ADC2 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC3 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC1/ADC2 clock source and mode. + */ +#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#endif + +/** + * @brief ADC3 clock source and mode. + */ +#if !defined(STM32_ADC_ADC3_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Supported devices checks.*/ +#if !defined(STM32H7XX) +#error "ADCv4 only supports H7 STM32 devices" +#endif + +/* Registry checks.*/ +#if !defined(STM32_HAS_ADC1) || !defined(STM32_HAS_ADC2) || \ + !defined(STM32_HAS_ADC3) +#error "STM32_HAS_ADCx not defined in registry" +#endif + +/* Units checks.*/ +#if STM32_ADC_USE_ADC12 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if STM32_ADC_DUAL_MODE && !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 + +/* IRQ handlers checks.*/ +#if STM32_HAS_ADC1 && !defined(STM32_ADC12_HANDLER) +#error "STM32_ADC12_HANDLER not defined in registry" +#endif + +#if STM32_HAS_ADC2 && !defined(STM32_ADC12_HANDLER) +#error "STM32_ADC12_HANDLER not defined in registry" +#endif + +#if STM32_HAS_ADC3 && !defined(STM32_ADC3_HANDLER) +#error "STM32_ADC3_HANDLER not defined in registry" +#endif + +/* IRQ vector numbers checks.*/ +#if STM32_HAS_ADC1 && !defined(STM32_ADC12_NUMBER) +#error "STM32_ADC12_NUMBER not defined in registry" +#endif + +#if STM32_HAS_ADC2 && !defined(STM32_ADC12_NUMBER) +#error "STM32_ADC12_NUMBER not defined in registry" +#endif + +#if STM32_HAS_ADC3 && !defined(STM32_ADC3_NUMBER) +#error "STM32_ADC3_NUMBER not defined in registry" +#endif + +/* At least one ADC must be assigned.*/ +#if !STM32_ADC_USE_ADC12 && !STM32_ADC_USE_ADC3 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +/* Dual mode is only supported with ADC12.*/ +#if !STM32_ADC_USE_ADC12 && STM32_ADC_DUAL_MODE +#error "STM32_ADC_DUAL_MODE only supported with ADC12" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_ADC_USE_ADC12 && !defined(STM32_ADC_ADC12_DMA_STREAM) +#error "STM32_ADC_ADC12_DMA_STREAM not defined" +#endif + +#if STM32_ADC_USE_ADC3 && !defined(STM32_ADC_ADC3_BDMA_STREAM) +#error "STM32_ADC_ADC3_BDMA_STREAM not defined" +#endif + +/* DMA channel range tests.*/ +#if STM32_ADC_USE_ADC12 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_ADC_ADC12_DMA_STREAM) +#error "Invalid DMA channel assigned to ADC12" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !STM32_BDMA_IS_VALID_STREAM(STM32_ADC_ADC3_BDMA_STREAM) +#error "Invalid DMA channel assigned to ADC3" +#endif + +/* DMA priority tests.*/ +#if STM32_ADC_USE_ADC12 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC12_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC3" +#endif + +/* ADC IRQ priority tests.*/ +#if STM32_ADC_USE_ADC12 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC3" +#endif + +#if ((STM32_ADC_SAMPLES_SIZE != 8) && \ + (STM32_ADC_SAMPLES_SIZE != 16) && \ + (STM32_ADC_SAMPLES_SIZE != 32)) +#error "STM32_ADC_SAMPLES_SIZE must be 8, 16 or 32" +#endif + +#if (STM32_ADC_SAMPLES_SIZE != 32) && STM32_ADC_DUAL_MODE +#error "STM32_ADC_SAMPLES_SIZE = 32 not compatible with STM32_ADC_DUAL_MODE" +#endif + +#if !defined(STM32_ENFORCE_H7_REV_XY) +/* ADC clock source checks.*/ +#if (STM32_D1HPRE == STM32_D1HPRE_DIV1) +#define STM32_ADC_SCLK STM32_HCLK +#else +#define STM32_ADC_SCLK (STM32_HCLK / 2) +#endif + +#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +/* CHTODO: also check ADC_CCR_PRESC.*/ +#define STM32_ADC12_CLOCK (STM32_ADCCLK / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 1 / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 2 / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 4 / 2) +#else +#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" +#endif + +#if STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +/* CHTODO: also check ADC_CCR_PRESC.*/ +#define STM32_ADC3_CLOCK (STM32_ADCCLK / 2) +#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 1 / 2) +#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 2 / 2) +#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 4 / 2) +#else +#error "invalid clock mode selected for STM32_ADC_ADC3_CLOCK_MODE" +#endif + +#else /* defined(STM32_ENFORCE_H7_REV_XY) */ + +#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC12_CLOCK STM32_ADCCLK +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC12_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC12_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC12_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" +#endif + +#if STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC3_CLOCK STM32_ADCCLK +#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC3_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC3_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC3_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC3_CLOCK_MODE" +#endif + +#endif /* defined(STM32_ENFORCE_H7_REV_XY) */ + +#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +#if STM32_ADC3_CLOCK > STM32_ADCCLK_MAX +#error "STM32_ADC3_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +#if !defined(STM32_ENFORCE_H7_REV_XY) +/* ADC boost checks.*/ +#if STM32_ADC12_CLOCK > 6250000 +#define STM32_ADC12_BOOST (1U << 8U) +#elif STM32_ADC12_CLOCK > 12500000 +#define STM32_ADC12_BOOST (2U << 8U) +#elif STM32_ADC12_CLOCK > 25000000 +#define STM32_ADC12_BOOST (3U << 8U) +#else +#define STM32_ADC12_BOOST (0U << 8U) +#endif + +#if STM32_ADC3_CLOCK > 6250000 +#define STM32_ADC3_BOOST (1U << 8U) +#elif STM32_ADC3_CLOCK > 12500000 +#define STM32_ADC3_BOOST (2U << 8U) +#elif STM32_ADC3_CLOCK > 25000000 +#define STM32_ADC3_BOOST (3U << 8U) +#else +#define STM32_ADC3_BOOST (0U << 8U) +#endif + +#else /* defined(STM32_ENFORCE_H7_REV_XY) */ + +#if STM32_ADC12_CLOCK > 20000000 +#define STM32_ADC12_BOOST (1U << 8U) +#else +#define STM32_ADC12_BOOST (0U << 8U) +#endif + +#if STM32_ADC3_CLOCK > 20000000 +#define STM32_ADC3_BOOST (1U << 8U) +#else +#define STM32_ADC3_BOOST (0U << 8U) +#endif + +#endif /* defined(STM32_ENFORCE_H7_REV_XY) */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +#if STM32_ADC_USE_ADC12 +#define STM32_ADC_DMA_REQUIRED +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif +#endif + +#if STM32_ADC_USE_ADC3 +#define STM32_ADC_BDMA_REQUIRED +#if !defined(STM32_BDMA_REQUIRED) +#define STM32_BDMA_REQUIRED +#endif +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +#if (STM32_ADC_SAMPLES_SIZE == 16) || defined(__DOXYGEN__) +typedef uint16_t adcsample_t; +#elif (STM32_ADC_SAMPLES_SIZE == 8) +typedef uint8_t adcsample_t; +#elif (STM32_ADC_SAMPLES_SIZE == 32) +typedef uint32_t adcsample_t; +#endif + +/** + * @brief Channels number in a conversion group. + */ +typedef uint32_t adc_channels_num_t; + +/** + * @brief Type of an ADC error mask. + */ +typedef uint32_t adcerror_t; + +/** + * @brief Type of a DMA channel pointer choice. + */ +typedef union { +#if defined(STM32_ADC_DMA_REQUIRED) || defined(__DOXYGEN__) + /** + * @brief DMA stream. + */ + const stm32_dma_stream_t *dma; +#endif +#if defined(STM32_ADC_BDMA_REQUIRED) || defined(__DOXYGEN__) + /** + * @brief BDMA stream. + */ + const stm32_bdma_stream_t *bdma; +#endif +} adc_ldd_dma_reference_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) +#define adc_lld_driver_fields \ + /* Pointer to the master ADCx registers block.*/ \ + ADC_TypeDef *adcm; \ + /* Pointer to the slave ADCx registers block.*/ \ + ADC_TypeDef *adcs; \ + /* Pointer to the common ADCx_y registers block.*/ \ + ADC_Common_TypeDef *adcc; \ + /* Pointer to associated DMA channel.*/ \ + adc_ldd_dma_reference_t data; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode +#else +#define adc_lld_driver_fields \ + /* Pointer to the master ADCx registers block.*/ \ + ADC_TypeDef *adcm; \ + /* Pointer to the slave ADCx registers block.*/ \ + ADC_Common_TypeDef *adcc; \ + /* Pointer to associated DMA channel.*/ \ + adc_ldd_dma_reference_t data; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode +#endif + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* ADC DIFSEL register initialization data.*/ \ + uint32_t difsel; \ + /* Calibration mode, specify ADCCALIN and/or ADCCALDIF bits in here.*/ \ + uint32_t calibration + +#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__) +#define adc_lld_configuration_group_fields \ + /* ADC CFGR register initialization data. \ + NOTE: The bits DMAEN and DMACFG are enforced internally \ + to the driver, keep them to zero. \ + NOTE: The bits @p ADC_CFGR_CONT or @p ADC_CFGR_DISCEN must be \ + specified in continuous mode or if the buffer depth is \ + greater than one.*/ \ + uint32_t cfgr; \ + /* ADC CFGR2 register initialization data. \ + NOTE: Put this field to zero if not using oversampling.*/ \ + uint32_t cfgr2; \ + /* ADC CCR register initialization data*/ \ + uint32_t ccr; \ + /* ADC PCSEL register initialization data.*/ \ + uint32_t pcsel; \ + /* ADC LTR1 register initialization data.*/ \ + uint32_t ltr1; \ + /* ADC HTR1 register initialization data.*/ \ + uint32_t htr1; \ + /* ADC LTR2 register initialization data.*/ \ + uint32_t ltr2; \ + /* ADC HTR2 register initialization data.*/ \ + uint32_t htr2; \ + /* ADC LTR3 register initialization data.*/ \ + uint32_t ltr3; \ + /* ADC HTR3 register initialization data.*/ \ + uint32_t htr3; \ + /* ADC AWD2CR register initialization data.*/ \ + uint32_t awd2cr; \ + /* ADC AWD3CR register initialization data.*/ \ + uint32_t awd3cr; \ + /* ADC SMPRx registers initialization data.*/ \ + uint32_t smpr[2]; \ + /* ADC SQRx register initialization data.*/ \ + uint32_t sqr[4]; \ + /* Slave ADC LTR/HTRx registers initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t sltr1; \ + uint32_t shtr1; \ + uint32_t sltr2; \ + uint32_t shtr2; \ + uint32_t sltr3; \ + uint32_t shtr3; \ + /* Slave ADC AWDxCR registers initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t sawd2cr; \ + uint32_t sawd3cr; \ + /* Slave ADC SMPRx registers initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t ssmpr[2]; \ + /* Slave ADC SQRx register initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t ssqr[4] +#else /* STM32_ADC_DUAL_MODE == FALSE */ +#define adc_lld_configuration_group_fields \ + uint32_t cfgr; \ + uint32_t cfgr2; \ + uint32_t ccr; \ + uint32_t pcsel; \ + uint32_t ltr1; \ + uint32_t htr1; \ + uint32_t ltr2; \ + uint32_t htr2; \ + uint32_t ltr3; \ + uint32_t htr3; \ + uint32_t awd2cr; \ + uint32_t awd3cr; \ + uint32_t smpr[2]; \ + uint32_t sqr[4] +#endif /* STM32_ADC_DUAL_MODE == FALSE */ + +/** + * @name Sequences building helper macros + * @{ + */ +/** + * @brief Number of channels in a conversion sequence. + */ +#define ADC_SQR1_NUM_CH(n) (((n) - 1U) << 0U) + +#define ADC_SQR1_SQ1_N(n) ((n) << 6U) /**< @brief 1st channel in seq. */ +#define ADC_SQR1_SQ2_N(n) ((n) << 12U)/**< @brief 2nd channel in seq. */ +#define ADC_SQR1_SQ3_N(n) ((n) << 18U)/**< @brief 3rd channel in seq. */ +#define ADC_SQR1_SQ4_N(n) ((n) << 24U)/**< @brief 4th channel in seq. */ + +#define ADC_SQR2_SQ5_N(n) ((n) << 0U) /**< @brief 5th channel in seq. */ +#define ADC_SQR2_SQ6_N(n) ((n) << 6U) /**< @brief 6th channel in seq. */ +#define ADC_SQR2_SQ7_N(n) ((n) << 12U)/**< @brief 7th channel in seq. */ +#define ADC_SQR2_SQ8_N(n) ((n) << 18U)/**< @brief 8th channel in seq. */ +#define ADC_SQR2_SQ9_N(n) ((n) << 24U)/**< @brief 9th channel in seq. */ + +#define ADC_SQR3_SQ10_N(n) ((n) << 0U) /**< @brief 10th channel in seq.*/ +#define ADC_SQR3_SQ11_N(n) ((n) << 6U) /**< @brief 11th channel in seq.*/ +#define ADC_SQR3_SQ12_N(n) ((n) << 12U)/**< @brief 12th channel in seq.*/ +#define ADC_SQR3_SQ13_N(n) ((n) << 18U)/**< @brief 13th channel in seq.*/ +#define ADC_SQR3_SQ14_N(n) ((n) << 24U)/**< @brief 14th channel in seq.*/ + +#define ADC_SQR4_SQ15_N(n) ((n) << 0U) /**< @brief 15th channel in seq.*/ +#define ADC_SQR4_SQ16_N(n) ((n) << 6U) /**< @brief 16th channel in seq.*/ +/** @} */ + +/** + * @name Sampling rate settings helper macros + * @{ + */ +#define ADC_SMPR1_SMP_AN0(n) ((n) << 0U) /**< @brief AN0 sampling time. */ +#define ADC_SMPR1_SMP_AN1(n) ((n) << 3U) /**< @brief AN1 sampling time. */ +#define ADC_SMPR1_SMP_AN2(n) ((n) << 6U) /**< @brief AN2 sampling time. */ +#define ADC_SMPR1_SMP_AN3(n) ((n) << 9U) /**< @brief AN3 sampling time. */ +#define ADC_SMPR1_SMP_AN4(n) ((n) << 12U)/**< @brief AN4 sampling time. */ +#define ADC_SMPR1_SMP_AN5(n) ((n) << 15U)/**< @brief AN5 sampling time. */ +#define ADC_SMPR1_SMP_AN6(n) ((n) << 18U)/**< @brief AN6 sampling time. */ +#define ADC_SMPR1_SMP_AN7(n) ((n) << 21U)/**< @brief AN7 sampling time. */ +#define ADC_SMPR1_SMP_AN8(n) ((n) << 24U)/**< @brief AN8 sampling time. */ +#define ADC_SMPR1_SMP_AN9(n) ((n) << 27U)/**< @brief AN9 sampling time. */ + +#define ADC_SMPR2_SMP_AN10(n) ((n) << 0U) /**< @brief AN10 sampling time. */ +#define ADC_SMPR2_SMP_AN11(n) ((n) << 3U) /**< @brief AN11 sampling time. */ +#define ADC_SMPR2_SMP_AN12(n) ((n) << 6U) /**< @brief AN12 sampling time. */ +#define ADC_SMPR2_SMP_AN13(n) ((n) << 9U) /**< @brief AN13 sampling time. */ +#define ADC_SMPR2_SMP_AN14(n) ((n) << 12U)/**< @brief AN14 sampling time. */ +#define ADC_SMPR2_SMP_AN15(n) ((n) << 15U)/**< @brief AN15 sampling time. */ +#define ADC_SMPR2_SMP_AN16(n) ((n) << 18U)/**< @brief AN16 sampling time. */ +#define ADC_SMPR2_SMP_AN17(n) ((n) << 21U)/**< @brief AN17 sampling time. */ +#define ADC_SMPR2_SMP_AN18(n) ((n) << 24U)/**< @brief AN18 sampling time. */ +#define ADC_SMPR2_SMP_AN19(n) ((n) << 27U)/**< @brief AN19 sampling time. */ +/** @} */ + +/** + * @name Analog watchdog settings helper macros + * @{ + */ +#define ADC_CFGR_AWD1_N(n) ((n) << 26U)/**< @brief AWD1 channel number */ +#define ADC_AWD23_MASK(n) (1U << (n)) /**< @brief AWD2/3 channels mask*/ +/** @} */ + +/** + * @name Oversampling settings helper macros + * @{ + */ +#define ADC_CFGR2_OVSS_N(n) ((n) << 5U)/**< @brief ovsr right shift */ +#define ADC_CFGR2_OVSR_N(n) ((n) << 16U)/**< @brief oversampling ratio */ +#define ADC_CFGR2_LSHIFT_N(n) ((n) << 28U)/**< @brief ovsr left shift */ + +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC12 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#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 adcSTM32EnableVREF(ADCDriver *adcp); + void adcSTM32DisableVREF(ADCDriver *adcp); + void adcSTM32EnableTS(ADCDriver *adcp); + void adcSTM32DisableTS(ADCDriver *adcp); + void adcSTM32EnableVBAT(ADCDriver *adcp); + void adcSTM32DisableVBAT(ADCDriver *adcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv4/notes.txt b/os/hal/ports/STM32/LLD/ADCv4/notes.txt index d0b59b7175..6c58ab8ea0 100644 --- a/os/hal/ports/STM32/LLD/ADCv4/notes.txt +++ b/os/hal/ports/STM32/LLD/ADCv4/notes.txt @@ -1,13 +1,13 @@ -STM32 ADCv4 driver. - -Driver capability: - -- Supports the STM32 "fast" ADC found on H7 sub-family. - -The file registry must export: - -STM32_HAS_ADCx - ADCx presence flag (1..4). -STM32_ADC12_HANDLER - IRQ vector name for ADC1 and ADC2. -STM32_ADC12_NUMBER - IRQ vector number for ADC1 and ADC2. -STM32_ADC34_HANDLER - IRQ vector name for ADC3 and ADC4. -STM32_ADC34_NUMBER - IRQ vector number for ADC3 and ADC4. +STM32 ADCv4 driver. + +Driver capability: + +- Supports the STM32 "fast" ADC found on H7 sub-family. + +The file registry must export: + +STM32_HAS_ADCx - ADCx presence flag (1..4). +STM32_ADC12_HANDLER - IRQ vector name for ADC1 and ADC2. +STM32_ADC12_NUMBER - IRQ vector number for ADC1 and ADC2. +STM32_ADC34_HANDLER - IRQ vector name for ADC3 and ADC4. +STM32_ADC34_NUMBER - IRQ vector number for ADC3 and ADC4. diff --git a/os/hal/ports/STM32/LLD/ADCv5/driver.mk b/os/hal/ports/STM32/LLD/ADCv5/driver.mk index 1774fca70d..2fab87d272 100644 --- a/os/hal/ports/STM32/LLD/ADCv5/driver.mk +++ b/os/hal/ports/STM32/LLD/ADCv5/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5 diff --git a/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c index 30636094e7..ad4e6e4aa3 100644 --- a/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c +++ b/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c @@ -1,483 +1,483 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv1/hal_adc_lld.c - * @brief STM32 ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define ADC1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief ADC voltage regulator enable. - * - * @param[in] adc pointer to the ADC registers block - */ -NOINLINE static void adc_lld_vreg_on(ADC_TypeDef *adc) { - - osalDbgAssert(adc->CR == 0, "invalid register state"); - -#if defined(ADC_CR_ADVREGEN) - adc->CR = ADC_CR_ADVREGEN; - volatile uint32_t loop = (STM32_HCLK >> 20) << 4; - do { - loop--; - } while (loop > 0); -#else -#endif -} - -/** - * @brief Calibrates an ADC unit. - * - * @param[in] adc pointer to the ADC registers block - */ -static void adc_lld_calibrate(ADC_TypeDef *adc) { - - adc->CR |= ADC_CR_ADCAL; - while (adc->CR & ADC_CR_ADCAL) { - /* Waiting for calibration end.*/ - } - adc->CR = 0U; -} - -/** - * @brief Stops an ongoing conversion, if any. - * - * @param[in] adc pointer to the ADC registers block - */ -static void adc_lld_stop_adc(ADC_TypeDef *adc) { - - if (adc->CR & ADC_CR_ADSTART) { - adc->CR |= ADC_CR_ADSTP; - while (adc->CR & ADC_CR_ADSTP) - ; - adc->IER = 0; - } - - /* Disabling the ADC.*/ - adc->CR |= ADC_CR_ADDIS; - while ((adc->CR & ADC_CR_ADDIS) != 0U) { - /* Waiting for ADC to be disabled.*/ - } -} - -/** - * @brief ADC DMA service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -#if !defined(STM32_ADC1_HANDLER) -#error "STM32_ADC1_HANDLER not defined" -#endif -/** - * @brief ADC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - adc_lld_serve_interrupt(&ADCD1); - -#if defined(STM32_ADC_ADC1_IRQ_HOOK) - STM32_ADC_ADC1_IRQ_HOOK -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = NULL; - 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; - - /* The vector is initialized on driver initialization and never - disabled.*/ - nvicEnableVector(12, STM32_ADC_ADC1_IRQ_PRIORITY); -#endif -} - -/** - * @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) { - adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - rccEnableADC1(true); - - /* DMA setup.*/ - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1); - - /* Clock settings.*/ - adcp->adc->CFGR2 = STM32_ADC_ADC1_CKMODE; - } -#endif /* STM32_ADC_USE_ADC1 */ - - /* Regulator enabled and stabilized.*/ - adc_lld_vreg_on(ADC1); - - /* Calibrating ADC.*/ - adc_lld_calibrate(adcp->adc); - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - - /* Restoring CCR default.*/ - ADC1_COMMON->CCR = STM32_ADC_PRESC << 18; - - /* Regulator off.*/ - adcp->adc->CR = 0; - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC1(); -#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, cfgr1, cfgr2; - const ADCConversionGroup *grpp = adcp->grpp; - - /* Starting the ADC enable procedure.*/ - adcp->adc->ISR = adcp->adc->ISR; - adcp->adc->CR = ADC_CR_ADEN; - - /* DMA setup.*/ - mode = adcp->dmamode; - cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN; - cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - cfgr1 |= ADC_CFGR1_DMACFG; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* Ensuring that the ADC finished the enable procedure.*/ - while ((adcp->adc->ISR & ADC_ISR_ADRDY) == 0U) { - /* Waiting for ADC to be stable.*/ - } - - /* ADC setup, if it is defined a callback for the analog watch dog then it - is enabled.*/ - if (grpp->error_cb != NULL) { - adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE - | ADC_IER_AWD2IE - | ADC_IER_AWD3IE; - adcp->adc->TR1 = grpp->tr1; - adcp->adc->TR2 = grpp->tr2; - adcp->adc->TR3 = grpp->tr3; - adcp->adc->AWD2CR = grpp->awd2cr; - adcp->adc->AWD3CR = grpp->awd3cr; - } - adcp->adc->SMPR = grpp->smpr; - adcp->adc->CHSELR = grpp->chselr; - - /* ADC configuration and start.*/ - adcp->adc->CFGR1 = cfgr1; - adcp->adc->CFGR2 = cfgr2 | grpp->cfgr2; - - /* ADC conversion start.*/ - adcp->adc->CR |= ADC_CR_ADSTART; -} - -/** - * @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); - adc_lld_stop_adc(adcp->adc); -} - -/** - * @brief ISR code. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_serve_interrupt(ADCDriver *adcp) { - uint32_t isr; - - isr = adcp->adc->ISR; - adcp->adc->ISR = isr; - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - adcerror_t emask = 0U; - - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the state is checked too.*/ - if ((isr & ADC_ISR_OVR) && (adcp->state == ADC_ACTIVE)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - emask |= ADC_ERR_OVERFLOW; - } - if (isr & ADC_ISR_AWD1) { - /* Analog watchdog 1 error.*/ - emask |= ADC_ERR_AWD1; - } - if (isr & ADC_ISR_AWD2) { - /* Analog watchdog 2 error.*/ - emask |= ADC_ERR_AWD2; - } - if (isr & ADC_ISR_AWD3) { - /* Analog watchdog 3 error.*/ - emask |= ADC_ERR_AWD3; - } - if (emask != 0U) { - _adc_isr_error_code(adcp, emask); - } - } -} - -/** - * @brief Enables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVREF(ADCDriver *adcp) { - - (void)adcp; - - ADC1_COMMON->CCR |= ADC_CCR_VREFEN; -} - -/** - * @brief Disables the VREFEN bit. - * @details The VREFEN bit is required in order to sample the VREF channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVREF(ADCDriver *adcp) { - - (void)adcp; - - ADC1_COMMON->CCR &= ~ADC_CCR_VREFEN; -} - -/** - * @brief Enables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableTS(ADCDriver *adcp) { - - (void)adcp; - - ADC1_COMMON->CCR |= ADC_CCR_TSEN; -} - -/** - * @brief Disables the TSEN bit. - * @details The TSEN bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableTS(ADCDriver *adcp) { - - (void)adcp; - - ADC1_COMMON->CCR &= ~ADC_CCR_TSEN; -} - -#if defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__) -/** - * @brief Enables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32EnableVBAT(ADCDriver *adcp) { - - (void)adcp; - - ADC1_COMMON->CCR |= ADC_CCR_VBATEN; -} - -/** - * @brief Disables the VBATEN bit. - * @details The VBATEN bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adcSTM32DisableVBAT(ADCDriver *adcp) { - - (void)adcp; - - ADC1_COMMON->CCR &= ~ADC_CCR_VBATEN; -} -#endif /* defined(ADC_CCR_VBATEN) */ - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv1/hal_adc_lld.c + * @brief STM32 ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define ADC1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief ADC voltage regulator enable. + * + * @param[in] adc pointer to the ADC registers block + */ +NOINLINE static void adc_lld_vreg_on(ADC_TypeDef *adc) { + + osalDbgAssert(adc->CR == 0, "invalid register state"); + +#if defined(ADC_CR_ADVREGEN) + adc->CR = ADC_CR_ADVREGEN; + volatile uint32_t loop = (STM32_HCLK >> 20) << 4; + do { + loop--; + } while (loop > 0); +#else +#endif +} + +/** + * @brief Calibrates an ADC unit. + * + * @param[in] adc pointer to the ADC registers block + */ +static void adc_lld_calibrate(ADC_TypeDef *adc) { + + adc->CR |= ADC_CR_ADCAL; + while (adc->CR & ADC_CR_ADCAL) { + /* Waiting for calibration end.*/ + } + adc->CR = 0U; +} + +/** + * @brief Stops an ongoing conversion, if any. + * + * @param[in] adc pointer to the ADC registers block + */ +static void adc_lld_stop_adc(ADC_TypeDef *adc) { + + if (adc->CR & ADC_CR_ADSTART) { + adc->CR |= ADC_CR_ADSTP; + while (adc->CR & ADC_CR_ADSTP) + ; + adc->IER = 0; + } + + /* Disabling the ADC.*/ + adc->CR |= ADC_CR_ADDIS; + while ((adc->CR & ADC_CR_ADDIS) != 0U) { + /* Waiting for ADC to be disabled.*/ + } +} + +/** + * @brief ADC DMA service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +#if !defined(STM32_ADC1_HANDLER) +#error "STM32_ADC1_HANDLER not defined" +#endif +/** + * @brief ADC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + adc_lld_serve_interrupt(&ADCD1); + +#if defined(STM32_ADC_ADC1_IRQ_HOOK) + STM32_ADC_ADC1_IRQ_HOOK +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = NULL; + 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; + + /* The vector is initialized on driver initialization and never + disabled.*/ + nvicEnableVector(12, STM32_ADC_ADC1_IRQ_PRIORITY); +#endif +} + +/** + * @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) { + adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM, + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + rccEnableADC1(true); + + /* DMA setup.*/ + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1); + + /* Clock settings.*/ + adcp->adc->CFGR2 = STM32_ADC_ADC1_CKMODE; + } +#endif /* STM32_ADC_USE_ADC1 */ + + /* Regulator enabled and stabilized.*/ + adc_lld_vreg_on(ADC1); + + /* Calibrating ADC.*/ + adc_lld_calibrate(adcp->adc); + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + + /* Restoring CCR default.*/ + ADC1_COMMON->CCR = STM32_ADC_PRESC << 18; + + /* Regulator off.*/ + adcp->adc->CR = 0; + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC1(); +#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, cfgr1, cfgr2; + const ADCConversionGroup *grpp = adcp->grpp; + + /* Starting the ADC enable procedure.*/ + adcp->adc->ISR = adcp->adc->ISR; + adcp->adc->CR = ADC_CR_ADEN; + + /* DMA setup.*/ + mode = adcp->dmamode; + cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN; + cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + cfgr1 |= ADC_CFGR1_DMACFG; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* Ensuring that the ADC finished the enable procedure.*/ + while ((adcp->adc->ISR & ADC_ISR_ADRDY) == 0U) { + /* Waiting for ADC to be stable.*/ + } + + /* ADC setup, if it is defined a callback for the analog watch dog then it + is enabled.*/ + if (grpp->error_cb != NULL) { + adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE + | ADC_IER_AWD2IE + | ADC_IER_AWD3IE; + adcp->adc->TR1 = grpp->tr1; + adcp->adc->TR2 = grpp->tr2; + adcp->adc->TR3 = grpp->tr3; + adcp->adc->AWD2CR = grpp->awd2cr; + adcp->adc->AWD3CR = grpp->awd3cr; + } + adcp->adc->SMPR = grpp->smpr; + adcp->adc->CHSELR = grpp->chselr; + + /* ADC configuration and start.*/ + adcp->adc->CFGR1 = cfgr1; + adcp->adc->CFGR2 = cfgr2 | grpp->cfgr2; + + /* ADC conversion start.*/ + adcp->adc->CR |= ADC_CR_ADSTART; +} + +/** + * @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); + adc_lld_stop_adc(adcp->adc); +} + +/** + * @brief ISR code. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_serve_interrupt(ADCDriver *adcp) { + uint32_t isr; + + isr = adcp->adc->ISR; + adcp->adc->ISR = isr; + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + adcerror_t emask = 0U; + + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the state is checked too.*/ + if ((isr & ADC_ISR_OVR) && (adcp->state == ADC_ACTIVE)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + emask |= ADC_ERR_OVERFLOW; + } + if (isr & ADC_ISR_AWD1) { + /* Analog watchdog 1 error.*/ + emask |= ADC_ERR_AWD1; + } + if (isr & ADC_ISR_AWD2) { + /* Analog watchdog 2 error.*/ + emask |= ADC_ERR_AWD2; + } + if (isr & ADC_ISR_AWD3) { + /* Analog watchdog 3 error.*/ + emask |= ADC_ERR_AWD3; + } + if (emask != 0U) { + _adc_isr_error_code(adcp, emask); + } + } +} + +/** + * @brief Enables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVREF(ADCDriver *adcp) { + + (void)adcp; + + ADC1_COMMON->CCR |= ADC_CCR_VREFEN; +} + +/** + * @brief Disables the VREFEN bit. + * @details The VREFEN bit is required in order to sample the VREF channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVREF(ADCDriver *adcp) { + + (void)adcp; + + ADC1_COMMON->CCR &= ~ADC_CCR_VREFEN; +} + +/** + * @brief Enables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableTS(ADCDriver *adcp) { + + (void)adcp; + + ADC1_COMMON->CCR |= ADC_CCR_TSEN; +} + +/** + * @brief Disables the TSEN bit. + * @details The TSEN bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableTS(ADCDriver *adcp) { + + (void)adcp; + + ADC1_COMMON->CCR &= ~ADC_CCR_TSEN; +} + +#if defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__) +/** + * @brief Enables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32EnableVBAT(ADCDriver *adcp) { + + (void)adcp; + + ADC1_COMMON->CCR |= ADC_CCR_VBATEN; +} + +/** + * @brief Disables the VBATEN bit. + * @details The VBATEN bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcSTM32DisableVBAT(ADCDriver *adcp) { + + (void)adcp; + + ADC1_COMMON->CCR &= ~ADC_CCR_VBATEN; +} +#endif /* defined(ADC_CCR_VBATEN) */ + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h b/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h index 4df334fc75..bf470f6b9a 100644 --- a/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h +++ b/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h @@ -1,405 +1,405 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ADCv1/hal_adc_lld.h - * @brief STM32 ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Possible ADC errors mask bits. - * @{ - */ -#define ADC_ERR_DMAFAILURE 1U /**< DMA operations failure. */ -#define ADC_ERR_OVERFLOW 2U /**< ADC overflow condition. */ -#define ADC_ERR_AWD1 4U /**< Watchdog 1 triggered. */ -#define ADC_ERR_AWD2 8U /**< Watchdog 2 triggered. */ -#define ADC_ERR_AWD3 16U /**< Watchdog 3 triggered. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */ -#define ADC_SMPR_SMP_3P5 1U /**< @brief 16 cycles conversion time. */ -#define ADC_SMPR_SMP_7P5 2U /**< @brief 20 cycles conversion time. */ -#define ADC_SMPR_SMP_12P5 3U /**< @brief 25 cycles conversion time. */ -#define ADC_SMPR_SMP_19P5 4U /**< @brief 31 cycles conversion time. */ -#define ADC_SMPR_SMP_39P5 5U /**< @brief 52 cycles conversion time. */ -#define ADC_SMPR_SMP_79P5 6U /**< @brief 92 cycles conversion time. */ -#define ADC_SMPR_SMP_160P5 7U /**< @brief 173 cycles conversion time. */ -/** @} */ - -/** - * @name CFGR1 register configuration helpers - * @{ - */ -#define ADC_CFGR1_RES_12BIT (0U << 3U) -#define ADC_CFGR1_RES_10BIT (1U << 3U) -#define ADC_CFGR1_RES_8BIT (2U << 3U) -#define ADC_CFGR1_RES_6BIT (3U << 3U) - -#define ADC_CFGR1_EXTSEL_MASK (15U << 6U) -#define ADC_CFGR1_EXTSEL_SRC(n) ((n) << 6U) - -#define ADC_CFGR1_EXTEN_MASK (3U << 10U) -#define ADC_CFGR1_EXTEN_DISABLED (0U << 10U) -#define ADC_CFGR1_EXTEN_RISING (1U << 10U) -#define ADC_CFGR1_EXTEN_FALLING (2U << 10U) -#define ADC_CFGR1_EXTEN_BOTH (3U << 10U) -/** @} */ - -/** - * @name CFGR2 register configuration helpers - * @{ - */ -#define STM32_ADC_CKMODE_MASK (3U << 30U) -#define STM32_ADC_CKMODE_ADCCLK (0U << 30U) -#define STM32_ADC_CKMODE_PCLK_DIV2 (1U << 30U) -#define STM32_ADC_CKMODE_PCLK_DIV4 (2U << 30U) -#define STM32_ADC_CKMODE_PCLK (3U << 30U) - -#define ADC_CFGR2_OVSR_MASK (7U << 2U) -#define ADC_CFGR2_OVSR_2X (0U << 2U) -#define ADC_CFGR2_OVSR_4X (1U << 2U) -#define ADC_CFGR2_OVSR_8X (2U << 2U) -#define ADC_CFGR2_OVSR_16X (3U << 2U) -#define ADC_CFGR2_OVSR_32X (4U << 2U) -#define ADC_CFGR2_OVSR_64X (5U << 2U) -#define ADC_CFGR2_OVSR_128X (6U << 2U) -#define ADC_CFGR2_OVSR_256X (7U << 2U) - -#define ADC_CFGR2_OVSS_MASK (15 << 5U) -#define ADC_CFGR2_OVSS_SHIFT(n) ((n) << 5U) -/** @} */ - -/** - * @name CHSELR register initializers for CHSELRMOD=0 - * @{ - */ -#define ADC_CHSELR_CHSEL_N(n) (1U << (n)) -/** @} */ - -/** - * @name CHSELR register initializers for CHSELRMOD=1 - * @{ - */ -#define ADC_CHSELR_SQ1_N(n) ((uint32_t)(n) << 0U) -#define ADC_CHSELR_SQ2_N(n) ((uint32_t)(n) << 4U) -#define ADC_CHSELR_SQ3_N(n) ((uint32_t)(n) << 8U) -#define ADC_CHSELR_SQ4_N(n) ((uint32_t)(n) << 12U) -#define ADC_CHSELR_SQ5_N(n) ((uint32_t)(n) << 16U) -#define ADC_CHSELR_SQ6_N(n) ((uint32_t)(n) << 20U) -#define ADC_CHSELR_SQ7_N(n) ((uint32_t)(n) << 24U) -#define ADC_CHSELR_SQ8_N(n) ((uint32_t)(n) << 28U) - -#define ADC_CHSELR_SQ1_END (15U << 0U) -#define ADC_CHSELR_SQ2_END (15U << 4U) -#define ADC_CHSELR_SQ3_END (15U << 8U) -#define ADC_CHSELR_SQ4_END (15U << 12U) -#define ADC_CHSELR_SQ5_END (15U << 16U) -#define ADC_CHSELR_SQ6_END (15U << 20U) -#define ADC_CHSELR_SQ7_END (15U << 24U) -#define ADC_CHSELR_SQ8_END (15U << 28U) -/** @} */ - -/** - * @name Threshold registers initializers - * @{ - */ -#define ADC_TR(low, high) (((uint32_t)(high) << 16U) | \ - (uint32_t)(low)) -#define ADC_TR_DISABLED ADC_TR(0U, 0x0FFFU) -#define ADC_AWDCR_ENABLE(n) (1U << (n)) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC1 clock source selection. - */ -#if !defined(STM32_ADC_ADC1_CKMODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK -#endif - -/** - * @brief ADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_IRQ_PRIORITY 2 -#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 2 -#endif - -/* - * @brief ADC prescaler setting. - * @note This setting has effect only in asynchronous clock mode (the - * default, @p STM32_ADC_CKMODE_ADCCLK). - */ -#if !defined(STM32_ADC_PRESCALER_VALUE) || defined(__DOXYGEN__) -#define STM32_ADC_PRESCALER_VALUE 2 -#endif - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Supported devices checks.*/ -#if !defined(STM32G0XX) && !defined(STM32WLXX) -#error "ADCv5 only supports G0 and WL STM32 devices" -#endif - -/* Registry checks.*/ -#if !defined(STM32_HAS_ADC1) -#error "STM32_HAS_ADC1 not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) -#error "STM32_ADC1_HANDLER not defined in registry" -#endif - -#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) -#error "STM32_ADC1_NUMBER not defined in registry" -#endif - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -/* Units checks.*/ -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -/* At least one ADC must be assigned.*/ -#if !STM32_ADC_USE_ADC1 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -/* ADC IRQ priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -/* DMA IRQ priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -/* DMA priority tests.*/ -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM) -#error "ADC DMA stream not defined" -#endif - -/* ADC clock source checks.*/ -#if STM32_ADC_PRESCALER_VALUE == 1 -#define STM32_ADC_PRESC 0U -#elif STM32_ADC_PRESCALER_VALUE == 2 -#define STM32_ADC_PRESC 1U -#elif STM32_ADC_PRESCALER_VALUE == 4 -#define STM32_ADC_PRESC 2U -#elif STM32_ADC_PRESCALER_VALUE == 6 -#define STM32_ADC_PRESC 3U -#elif STM32_ADC_PRESCALER_VALUE == 8 -#define STM32_ADC_PRESC 4U -#elif STM32_ADC_PRESCALER_VALUE == 10 -#define STM32_ADC_PRESC 5U -#elif STM32_ADC_PRESCALER_VALUE == 12 -#define STM32_ADC_PRESC 6U -#elif STM32_ADC_PRESCALER_VALUE == 16 -#define STM32_ADC_PRESC 7U -#elif STM32_ADC_PRESCALER_VALUE == 32 -#define STM32_ADC_PRESC 8U -#elif STM32_ADC_PRESCALER_VALUE == 64 -#define STM32_ADC_PRESC 9U -#elif STM32_ADC_PRESCALER_VALUE == 128 -#define STM32_ADC_PRESC 10U -#elif STM32_ADC_PRESCALER_VALUE == 256 -#define STM32_ADC_PRESC 11U -#else -#error "Invalid value assigned to STM32_ADC_PRESCALER_VALUE" -#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 Type of an ADC error mask. - */ -typedef uint32_t adcerror_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_configuration_group_fields \ - /* ADC CFGR1 register initialization data. \ - NOTE: The bits DMAEN and DMACFG are enforced internally \ - to the driver, keep them to zero. \ - NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \ - specified in continuous more or if the buffer depth is \ - greater than one.*/ \ - uint32_t cfgr1; \ - /* ADC CFGR2 register initialization data. \ - NOTE: CKMODE bits must not be specified in this field and left to \ - zero.*/ \ - uint32_t cfgr2; \ - /* ADC TR1 register initialization data.*/ \ - uint32_t tr1; \ - /* ADC TR2 register initialization data.*/ \ - uint32_t tr2; \ - /* ADC TR3 register initialization data.*/ \ - uint32_t tr3; \ - /* ADC AWD2CR register initialization data.*/ \ - uint32_t awd2cr; \ - /* ADC AWD3CR register initialization data.*/ \ - uint32_t awd3cr; \ - /* ADC SMPR register initialization data.*/ \ - uint32_t smpr; \ - /* ADC CHSELR register initialization data. \ - NOTE: The number of bits at logic level one in this register must \ - be equal to the number in the @p num_channels field.*/ \ - uint32_t chselr - -/** - * @brief Changes the value of the ADC CCR register. - * @details Use this function in order to enable or disable the internal - * analog sources. See the documentation in the STM32 Reference - * Manual. - * @note PRESC bits must not be specified and left to zero. - */ -#define adcSTM32SetCCR(ccr) (ADC1_COMMON->CCR = (ccr)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); - void adc_lld_serve_interrupt(ADCDriver *adcp); - void adcSTM32EnableVREF(ADCDriver *adcp); - void adcSTM32DisableVREF(ADCDriver *adcp); - void adcSTM32EnableTS(ADCDriver *adcp); - void adcSTM32DisableTS(ADCDriver *adcp); -#if defined(ADC_CCR_VBATEN) - void adcSTM32EnableVBAT(ADCDriver *adcp); - void adcSTM32DisableVBAT(ADCDriver *adcp); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv1/hal_adc_lld.h + * @brief STM32 ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Possible ADC errors mask bits. + * @{ + */ +#define ADC_ERR_DMAFAILURE 1U /**< DMA operations failure. */ +#define ADC_ERR_OVERFLOW 2U /**< ADC overflow condition. */ +#define ADC_ERR_AWD1 4U /**< Watchdog 1 triggered. */ +#define ADC_ERR_AWD2 8U /**< Watchdog 2 triggered. */ +#define ADC_ERR_AWD3 16U /**< Watchdog 3 triggered. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */ +#define ADC_SMPR_SMP_3P5 1U /**< @brief 16 cycles conversion time. */ +#define ADC_SMPR_SMP_7P5 2U /**< @brief 20 cycles conversion time. */ +#define ADC_SMPR_SMP_12P5 3U /**< @brief 25 cycles conversion time. */ +#define ADC_SMPR_SMP_19P5 4U /**< @brief 31 cycles conversion time. */ +#define ADC_SMPR_SMP_39P5 5U /**< @brief 52 cycles conversion time. */ +#define ADC_SMPR_SMP_79P5 6U /**< @brief 92 cycles conversion time. */ +#define ADC_SMPR_SMP_160P5 7U /**< @brief 173 cycles conversion time. */ +/** @} */ + +/** + * @name CFGR1 register configuration helpers + * @{ + */ +#define ADC_CFGR1_RES_12BIT (0U << 3U) +#define ADC_CFGR1_RES_10BIT (1U << 3U) +#define ADC_CFGR1_RES_8BIT (2U << 3U) +#define ADC_CFGR1_RES_6BIT (3U << 3U) + +#define ADC_CFGR1_EXTSEL_MASK (15U << 6U) +#define ADC_CFGR1_EXTSEL_SRC(n) ((n) << 6U) + +#define ADC_CFGR1_EXTEN_MASK (3U << 10U) +#define ADC_CFGR1_EXTEN_DISABLED (0U << 10U) +#define ADC_CFGR1_EXTEN_RISING (1U << 10U) +#define ADC_CFGR1_EXTEN_FALLING (2U << 10U) +#define ADC_CFGR1_EXTEN_BOTH (3U << 10U) +/** @} */ + +/** + * @name CFGR2 register configuration helpers + * @{ + */ +#define STM32_ADC_CKMODE_MASK (3U << 30U) +#define STM32_ADC_CKMODE_ADCCLK (0U << 30U) +#define STM32_ADC_CKMODE_PCLK_DIV2 (1U << 30U) +#define STM32_ADC_CKMODE_PCLK_DIV4 (2U << 30U) +#define STM32_ADC_CKMODE_PCLK (3U << 30U) + +#define ADC_CFGR2_OVSR_MASK (7U << 2U) +#define ADC_CFGR2_OVSR_2X (0U << 2U) +#define ADC_CFGR2_OVSR_4X (1U << 2U) +#define ADC_CFGR2_OVSR_8X (2U << 2U) +#define ADC_CFGR2_OVSR_16X (3U << 2U) +#define ADC_CFGR2_OVSR_32X (4U << 2U) +#define ADC_CFGR2_OVSR_64X (5U << 2U) +#define ADC_CFGR2_OVSR_128X (6U << 2U) +#define ADC_CFGR2_OVSR_256X (7U << 2U) + +#define ADC_CFGR2_OVSS_MASK (15 << 5U) +#define ADC_CFGR2_OVSS_SHIFT(n) ((n) << 5U) +/** @} */ + +/** + * @name CHSELR register initializers for CHSELRMOD=0 + * @{ + */ +#define ADC_CHSELR_CHSEL_N(n) (1U << (n)) +/** @} */ + +/** + * @name CHSELR register initializers for CHSELRMOD=1 + * @{ + */ +#define ADC_CHSELR_SQ1_N(n) ((uint32_t)(n) << 0U) +#define ADC_CHSELR_SQ2_N(n) ((uint32_t)(n) << 4U) +#define ADC_CHSELR_SQ3_N(n) ((uint32_t)(n) << 8U) +#define ADC_CHSELR_SQ4_N(n) ((uint32_t)(n) << 12U) +#define ADC_CHSELR_SQ5_N(n) ((uint32_t)(n) << 16U) +#define ADC_CHSELR_SQ6_N(n) ((uint32_t)(n) << 20U) +#define ADC_CHSELR_SQ7_N(n) ((uint32_t)(n) << 24U) +#define ADC_CHSELR_SQ8_N(n) ((uint32_t)(n) << 28U) + +#define ADC_CHSELR_SQ1_END (15U << 0U) +#define ADC_CHSELR_SQ2_END (15U << 4U) +#define ADC_CHSELR_SQ3_END (15U << 8U) +#define ADC_CHSELR_SQ4_END (15U << 12U) +#define ADC_CHSELR_SQ5_END (15U << 16U) +#define ADC_CHSELR_SQ6_END (15U << 20U) +#define ADC_CHSELR_SQ7_END (15U << 24U) +#define ADC_CHSELR_SQ8_END (15U << 28U) +/** @} */ + +/** + * @name Threshold registers initializers + * @{ + */ +#define ADC_TR(low, high) (((uint32_t)(high) << 16U) | \ + (uint32_t)(low)) +#define ADC_TR_DISABLED ADC_TR(0U, 0x0FFFU) +#define ADC_AWDCR_ENABLE(n) (1U << (n)) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC1 clock source selection. + */ +#if !defined(STM32_ADC_ADC1_CKMODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK +#endif + +/** + * @brief ADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_IRQ_PRIORITY 2 +#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 2 +#endif + +/* + * @brief ADC prescaler setting. + * @note This setting has effect only in asynchronous clock mode (the + * default, @p STM32_ADC_CKMODE_ADCCLK). + */ +#if !defined(STM32_ADC_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_ADC_PRESCALER_VALUE 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Supported devices checks.*/ +#if !defined(STM32G0XX) && !defined(STM32WLXX) +#error "ADCv5 only supports G0 and WL STM32 devices" +#endif + +/* Registry checks.*/ +#if !defined(STM32_HAS_ADC1) +#error "STM32_HAS_ADC1 not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) +#error "STM32_ADC1_HANDLER not defined in registry" +#endif + +#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) +#error "STM32_ADC1_NUMBER not defined in registry" +#endif + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +/* Units checks.*/ +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +/* At least one ADC must be assigned.*/ +#if !STM32_ADC_USE_ADC1 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +/* ADC IRQ priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +/* DMA IRQ priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +/* DMA priority tests.*/ +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM) +#error "ADC DMA stream not defined" +#endif + +/* ADC clock source checks.*/ +#if STM32_ADC_PRESCALER_VALUE == 1 +#define STM32_ADC_PRESC 0U +#elif STM32_ADC_PRESCALER_VALUE == 2 +#define STM32_ADC_PRESC 1U +#elif STM32_ADC_PRESCALER_VALUE == 4 +#define STM32_ADC_PRESC 2U +#elif STM32_ADC_PRESCALER_VALUE == 6 +#define STM32_ADC_PRESC 3U +#elif STM32_ADC_PRESCALER_VALUE == 8 +#define STM32_ADC_PRESC 4U +#elif STM32_ADC_PRESCALER_VALUE == 10 +#define STM32_ADC_PRESC 5U +#elif STM32_ADC_PRESCALER_VALUE == 12 +#define STM32_ADC_PRESC 6U +#elif STM32_ADC_PRESCALER_VALUE == 16 +#define STM32_ADC_PRESC 7U +#elif STM32_ADC_PRESCALER_VALUE == 32 +#define STM32_ADC_PRESC 8U +#elif STM32_ADC_PRESCALER_VALUE == 64 +#define STM32_ADC_PRESC 9U +#elif STM32_ADC_PRESCALER_VALUE == 128 +#define STM32_ADC_PRESC 10U +#elif STM32_ADC_PRESCALER_VALUE == 256 +#define STM32_ADC_PRESC 11U +#else +#error "Invalid value assigned to STM32_ADC_PRESCALER_VALUE" +#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 Type of an ADC error mask. + */ +typedef uint32_t adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_configuration_group_fields \ + /* ADC CFGR1 register initialization data. \ + NOTE: The bits DMAEN and DMACFG are enforced internally \ + to the driver, keep them to zero. \ + NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \ + specified in continuous more or if the buffer depth is \ + greater than one.*/ \ + uint32_t cfgr1; \ + /* ADC CFGR2 register initialization data. \ + NOTE: CKMODE bits must not be specified in this field and left to \ + zero.*/ \ + uint32_t cfgr2; \ + /* ADC TR1 register initialization data.*/ \ + uint32_t tr1; \ + /* ADC TR2 register initialization data.*/ \ + uint32_t tr2; \ + /* ADC TR3 register initialization data.*/ \ + uint32_t tr3; \ + /* ADC AWD2CR register initialization data.*/ \ + uint32_t awd2cr; \ + /* ADC AWD3CR register initialization data.*/ \ + uint32_t awd3cr; \ + /* ADC SMPR register initialization data.*/ \ + uint32_t smpr; \ + /* ADC CHSELR register initialization data. \ + NOTE: The number of bits at logic level one in this register must \ + be equal to the number in the @p num_channels field.*/ \ + uint32_t chselr + +/** + * @brief Changes the value of the ADC CCR register. + * @details Use this function in order to enable or disable the internal + * analog sources. See the documentation in the STM32 Reference + * Manual. + * @note PRESC bits must not be specified and left to zero. + */ +#define adcSTM32SetCCR(ccr) (ADC1_COMMON->CCR = (ccr)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); + void adc_lld_serve_interrupt(ADCDriver *adcp); + void adcSTM32EnableVREF(ADCDriver *adcp); + void adcSTM32DisableVREF(ADCDriver *adcp); + void adcSTM32EnableTS(ADCDriver *adcp); + void adcSTM32DisableTS(ADCDriver *adcp); +#if defined(ADC_CCR_VBATEN) + void adcSTM32EnableVBAT(ADCDriver *adcp); + void adcSTM32DisableVBAT(ADCDriver *adcp); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/ADCv5/notes.txt b/os/hal/ports/STM32/LLD/ADCv5/notes.txt index 48ede4c0a5..71fe7490da 100644 --- a/os/hal/ports/STM32/LLD/ADCv5/notes.txt +++ b/os/hal/ports/STM32/LLD/ADCv5/notes.txt @@ -1,16 +1,16 @@ -STM32 ADCv5 driver. - -Driver capability: - -- Supports the STM32 "simple" ADC, the one found on small devices (G0). - -The file registry must export: - -STM32_HAS_ADC1 - ADC1 presence flag. -STM32_ADC_SUPPORTS_PRESCALER - Support of CCR PRESC field. -STM32_ADC_SUPPORTS_OVERSAMPLING - Support of oversampling-related fields. -STM32_ADC1_IRQ_SHARED_WITH_EXTI - TRUE if the IRQ is shared with EXTI. -STM32_ADC1_HANDLER - IRQ vector name. -STM32_ADC1_NUMBER - IRQ vector number. -STM32_ADC1_DMA_MSK - Mask of the compatible DMA channels. -STM32_ADC1_DMA_CHN - Mask of the channels mapping. +STM32 ADCv5 driver. + +Driver capability: + +- Supports the STM32 "simple" ADC, the one found on small devices (G0). + +The file registry must export: + +STM32_HAS_ADC1 - ADC1 presence flag. +STM32_ADC_SUPPORTS_PRESCALER - Support of CCR PRESC field. +STM32_ADC_SUPPORTS_OVERSAMPLING - Support of oversampling-related fields. +STM32_ADC1_IRQ_SHARED_WITH_EXTI - TRUE if the IRQ is shared with EXTI. +STM32_ADC1_HANDLER - IRQ vector name. +STM32_ADC1_NUMBER - IRQ vector number. +STM32_ADC1_DMA_MSK - Mask of the compatible DMA channels. +STM32_ADC1_DMA_CHN - Mask of the channels mapping. diff --git a/os/hal/ports/STM32/LLD/BDMAv1/driver.mk b/os/hal/ports/STM32/LLD/BDMAv1/driver.mk index 1146b41467..71ee1cabfb 100644 --- a/os/hal/ports/STM32/LLD/BDMAv1/driver.mk +++ b/os/hal/ports/STM32/LLD/BDMAv1/driver.mk @@ -1,2 +1,2 @@ -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1 diff --git a/os/hal/ports/STM32/LLD/BDMAv1/notes.txt b/os/hal/ports/STM32/LLD/BDMAv1/notes.txt index e7fe3ad1fc..5c1497d13f 100644 --- a/os/hal/ports/STM32/LLD/BDMAv1/notes.txt +++ b/os/hal/ports/STM32/LLD/BDMAv1/notes.txt @@ -1,11 +1,11 @@ -STM32 BDMAv1 driver. - -Driver capability: - -- The driver supports the "basic" DMA controller. - -The file registry must export: - -STM32_BDMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro - is not exported then the ISR is not declared. -STM32_BDMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7). +STM32 BDMAv1 driver. + +Driver capability: + +- The driver supports the "basic" DMA controller. + +The file registry must export: + +STM32_BDMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro + is not exported then the ISR is not declared. +STM32_BDMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7). diff --git a/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c b/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c index 4ca2e417bb..411a55b30f 100644 --- a/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c +++ b/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c @@ -1,455 +1,455 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file BDMAv1/stm32_bdma.c - * @brief BDMA helper driver code. - * - * @addtogroup STM32_BDMA - * @details BDMA sharing helper driver. In the STM32 the BDMA streams are a - * shared resource, this driver allows to allocate and free BDMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The BDMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating streams. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring BDMA services - has been enabled.*/ -#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the BDMA streams in @p bdma_allocated_mask. - */ -#define STM32_BDMA_STREAMS_MASK 0x000000FFU - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief BDMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_BDMA1_STREAM1, @p STM32_BDMA1_STREAM2 etc. - */ -const stm32_bdma_stream_t _stm32_bdma_streams[STM32_BDMA_STREAMS] = { - {BDMA, BDMA_Channel0, 0, DMAMUX2_Channel0, 0, STM32_BDMA1_CH0_NUMBER}, - {BDMA, BDMA_Channel1, 4, DMAMUX2_Channel1, 1, STM32_BDMA1_CH1_NUMBER}, - {BDMA, BDMA_Channel2, 8, DMAMUX2_Channel2, 2, STM32_BDMA1_CH2_NUMBER}, - {BDMA, BDMA_Channel3, 12, DMAMUX2_Channel3, 3, STM32_BDMA1_CH3_NUMBER}, - {BDMA, BDMA_Channel4, 16, DMAMUX2_Channel4, 4, STM32_BDMA1_CH4_NUMBER}, - {BDMA, BDMA_Channel5, 20, DMAMUX2_Channel5, 5, STM32_BDMA1_CH5_NUMBER}, - {BDMA, BDMA_Channel6, 24, DMAMUX2_Channel6, 6, STM32_BDMA1_CH6_NUMBER}, - {BDMA, BDMA_Channel7, 28, DMAMUX2_Channel7, 7, STM32_BDMA1_CH7_NUMBER} -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief BDMA ISR redirector type. - */ -typedef struct { - stm32_bdmaisr_t func; /**< @brief BDMA callback function. */ - void *param; /**< @brief BDMA callback parameter.*/ -} bdma_isr_redir_t; - -/** - * @brief BDMA driver base structure. - */ -static struct { - /** - * @brief Mask of the allocated streams. - */ - uint32_t allocated_mask; - /** - * @brief DMA IRQ redirectors. - */ - struct { - /** - * @brief DMA callback function. - */ - stm32_bdmaisr_t func; - /** - * @brief DMA callback parameter. - */ - void *param; - } streams[STM32_BDMA_STREAMS]; -} bdma; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief BDMA1 stream 0 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH0_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 0U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 0U; - if (bdma.streams[0].func) - bdma.streams[0].func(bdma.streams[0].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 1 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH1_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 4U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 4U; - if (bdma.streams[1].func) - bdma.streams[1].func(bdma.streams[1].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 2 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH2_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 8U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 8U; - if (bdma.streams[2].func) - bdma.streams[2].func(bdma.streams[2].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 3 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH3_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 12U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 12U; - if (bdma.streams[3].func) - bdma.streams[3].func(bdma.streams[3].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 4 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH4_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 16U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 16U; - if (bdma.streams[4].func) - bdma.streams[4].func(bdma.streams[4].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 5 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH5_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 20U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 20U; - if (bdma.streams[5].func) - bdma.streams[5].func(bdma.streams[5].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 6 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH6_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 24U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 24U; - if (bdma.streams[6].func) - bdma.streams[6].func(bdma.streams[6].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief BDMA1 stream 7 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_BDMA1_CH7_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (BDMA->ISR >> 28U) & STM32_BDMA_ISR_MASK; - BDMA->IFCR = flags << 28U; - if (bdma.streams[7].func) - bdma.streams[7].func(bdma.streams[7].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 BDMA helper initialization. - * - * @init - */ -void bdmaInit(void) { - unsigned i; - - bdma.allocated_mask = 0U; - for (i = 0; i < STM32_BDMA_STREAMS; i++) { - _stm32_bdma_streams[i].channel->CCR = 0U; - bdma.streams[i].func = NULL; - bdma.streams[i].param = NULL; - } - BDMA->IFCR = 0xFFFFFFFFU; -} - -/** - * @brief Allocates a BDMA stream. - * @details The stream is allocated and, if required, the BDMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific stream or: - * - @p STM32_BDMA_STREAM_ID_ANY for any stream. - * . - * @param[in] priority IRQ priority for the BDMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_bdma_stream_t - * structure. - * @retval NULL if a/the stream is not available. - * - * @iclass - */ -const stm32_bdma_stream_t *bdmaStreamAllocI(uint32_t id, - uint32_t priority, - stm32_bdmaisr_t func, - void *param) { - uint32_t i, startid, endid; - - osalDbgCheckClassI(); - - if (id < STM32_BDMA_STREAMS) { - startid = id; - endid = id; - } - else if (id == STM32_BDMA_STREAM_ID_ANY) { - startid = 0U; - endid = STM32_BDMA_STREAMS - 1U; - } - else { - osalDbgCheck(false); - return NULL; - } - - for (i = startid; i <= endid; i++) { - uint32_t mask = (1U << i); - if ((bdma.allocated_mask & mask) == 0U) { - const stm32_bdma_stream_t *stp = STM32_BDMA_STREAM(i); - - /* Installs the DMA handler.*/ - bdma.streams[i].func = func; - bdma.streams[i].param = param; - bdma.allocated_mask |= mask; - - /* Enabling DMA clocks required by the current streams set.*/ - if ((STM32_BDMA_STREAMS_MASK & mask) != 0U) { - rccEnableBDMA1(true); - } - -#if defined(rccEnableDMAMUX) - /* Enabling DMAMUX if present.*/ - if (bdma.allocated_mask != 0U) { - rccEnableDMAMUX(true); - } -#endif - - /* Enables the associated IRQ vector if not already enabled and if a - callback is defined.*/ - if (func != NULL) { - nvicEnableVector(stp->vector, priority); - } - - /* Putting the stream in a known state.*/ - bdmaStreamDisable(stp); - stp->channel->CCR = STM32_BDMA_CR_RESET_VALUE; - - return stp; - } - } - - return NULL; -} - -/** - * @brief Allocates a BDMA stream. - * @details The stream is allocated and, if required, the BDMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific stream or: - * - @p STM32_BDMA_STREAM_ID_ANY for any stream. - * . - * @param[in] priority IRQ priority for the BDMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_bdma_stream_t - * structure. - * @retval NULL if a/the stream is not available. - * - * @api - */ -const stm32_bdma_stream_t *bdmaStreamAlloc(uint32_t id, - uint32_t priority, - stm32_bdmaisr_t func, - void *param) { - const stm32_bdma_stream_t *stp; - - osalSysLock(); - stp = bdmaStreamAllocI(id, priority, func, param); - osalSysUnlock(); - - return stp; -} - -/** - * @brief Releases a BDMA stream. - * @details The stream is freed and, if required, the BDMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * - * @iclass - */ -void bdmaStreamFreeI(const stm32_bdma_stream_t *stp) { - - osalDbgCheck(stp != NULL); - - /* Check if the streams is not taken.*/ - osalDbgAssert((bdma.allocated_mask & (1U << stp->selfindex)) != 0U, - "not allocated"); - - /* Disables the associated IRQ vector.*/ - nvicDisableVector(stp->vector); - - /* Marks the stream as not allocated.*/ - bdma.allocated_mask &= ~(1U << stp->selfindex); - - /* Clearing associated handler and parameter.*/ - bdma.streams->func = NULL; - bdma.streams->param = NULL; - - /* Shutting down clocks that are no more required, if any.*/ - if ((bdma.allocated_mask & STM32_BDMA_STREAMS_MASK) == 0U) { - rccDisableBDMA1(); - } -} - -/** - * @brief Releases a BDMA stream. - * @details The stream is freed and, if required, the BDMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * - * @api - */ -void bdmaStreamFree(const stm32_bdma_stream_t *stp) { - - osalSysLock(); - bdmaStreamFreeI(stp); - osalSysUnlock(); -} - -/** - * @brief Associates a peripheral request to a BDMA stream. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] stp pointer to a @p stm32_bdma_stream_t structure - * @param[in] per peripheral identifier - * - * @special - */ -void bdmaSetRequestSource(const stm32_bdma_stream_t *stp, uint32_t per) { - - osalDbgCheck(per < 256U); - - stp->mux->CCR = per; -} - -#endif /* STM32_BDMA_REQUIRED */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file BDMAv1/stm32_bdma.c + * @brief BDMA helper driver code. + * + * @addtogroup STM32_BDMA + * @details BDMA sharing helper driver. In the STM32 the BDMA streams are a + * shared resource, this driver allows to allocate and free BDMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The BDMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating streams. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring BDMA services + has been enabled.*/ +#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the BDMA streams in @p bdma_allocated_mask. + */ +#define STM32_BDMA_STREAMS_MASK 0x000000FFU + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief BDMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_BDMA1_STREAM1, @p STM32_BDMA1_STREAM2 etc. + */ +const stm32_bdma_stream_t _stm32_bdma_streams[STM32_BDMA_STREAMS] = { + {BDMA, BDMA_Channel0, 0, DMAMUX2_Channel0, 0, STM32_BDMA1_CH0_NUMBER}, + {BDMA, BDMA_Channel1, 4, DMAMUX2_Channel1, 1, STM32_BDMA1_CH1_NUMBER}, + {BDMA, BDMA_Channel2, 8, DMAMUX2_Channel2, 2, STM32_BDMA1_CH2_NUMBER}, + {BDMA, BDMA_Channel3, 12, DMAMUX2_Channel3, 3, STM32_BDMA1_CH3_NUMBER}, + {BDMA, BDMA_Channel4, 16, DMAMUX2_Channel4, 4, STM32_BDMA1_CH4_NUMBER}, + {BDMA, BDMA_Channel5, 20, DMAMUX2_Channel5, 5, STM32_BDMA1_CH5_NUMBER}, + {BDMA, BDMA_Channel6, 24, DMAMUX2_Channel6, 6, STM32_BDMA1_CH6_NUMBER}, + {BDMA, BDMA_Channel7, 28, DMAMUX2_Channel7, 7, STM32_BDMA1_CH7_NUMBER} +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief BDMA ISR redirector type. + */ +typedef struct { + stm32_bdmaisr_t func; /**< @brief BDMA callback function. */ + void *param; /**< @brief BDMA callback parameter.*/ +} bdma_isr_redir_t; + +/** + * @brief BDMA driver base structure. + */ +static struct { + /** + * @brief Mask of the allocated streams. + */ + uint32_t allocated_mask; + /** + * @brief DMA IRQ redirectors. + */ + struct { + /** + * @brief DMA callback function. + */ + stm32_bdmaisr_t func; + /** + * @brief DMA callback parameter. + */ + void *param; + } streams[STM32_BDMA_STREAMS]; +} bdma; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief BDMA1 stream 0 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH0_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 0U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 0U; + if (bdma.streams[0].func) + bdma.streams[0].func(bdma.streams[0].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 1 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH1_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 4U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 4U; + if (bdma.streams[1].func) + bdma.streams[1].func(bdma.streams[1].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 2 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH2_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 8U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 8U; + if (bdma.streams[2].func) + bdma.streams[2].func(bdma.streams[2].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 3 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH3_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 12U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 12U; + if (bdma.streams[3].func) + bdma.streams[3].func(bdma.streams[3].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 4 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH4_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 16U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 16U; + if (bdma.streams[4].func) + bdma.streams[4].func(bdma.streams[4].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 5 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH5_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 20U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 20U; + if (bdma.streams[5].func) + bdma.streams[5].func(bdma.streams[5].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 6 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH6_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 24U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 24U; + if (bdma.streams[6].func) + bdma.streams[6].func(bdma.streams[6].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief BDMA1 stream 7 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_BDMA1_CH7_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (BDMA->ISR >> 28U) & STM32_BDMA_ISR_MASK; + BDMA->IFCR = flags << 28U; + if (bdma.streams[7].func) + bdma.streams[7].func(bdma.streams[7].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 BDMA helper initialization. + * + * @init + */ +void bdmaInit(void) { + unsigned i; + + bdma.allocated_mask = 0U; + for (i = 0; i < STM32_BDMA_STREAMS; i++) { + _stm32_bdma_streams[i].channel->CCR = 0U; + bdma.streams[i].func = NULL; + bdma.streams[i].param = NULL; + } + BDMA->IFCR = 0xFFFFFFFFU; +} + +/** + * @brief Allocates a BDMA stream. + * @details The stream is allocated and, if required, the BDMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific stream or: + * - @p STM32_BDMA_STREAM_ID_ANY for any stream. + * . + * @param[in] priority IRQ priority for the BDMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_bdma_stream_t + * structure. + * @retval NULL if a/the stream is not available. + * + * @iclass + */ +const stm32_bdma_stream_t *bdmaStreamAllocI(uint32_t id, + uint32_t priority, + stm32_bdmaisr_t func, + void *param) { + uint32_t i, startid, endid; + + osalDbgCheckClassI(); + + if (id < STM32_BDMA_STREAMS) { + startid = id; + endid = id; + } + else if (id == STM32_BDMA_STREAM_ID_ANY) { + startid = 0U; + endid = STM32_BDMA_STREAMS - 1U; + } + else { + osalDbgCheck(false); + return NULL; + } + + for (i = startid; i <= endid; i++) { + uint32_t mask = (1U << i); + if ((bdma.allocated_mask & mask) == 0U) { + const stm32_bdma_stream_t *stp = STM32_BDMA_STREAM(i); + + /* Installs the DMA handler.*/ + bdma.streams[i].func = func; + bdma.streams[i].param = param; + bdma.allocated_mask |= mask; + + /* Enabling DMA clocks required by the current streams set.*/ + if ((STM32_BDMA_STREAMS_MASK & mask) != 0U) { + rccEnableBDMA1(true); + } + +#if defined(rccEnableDMAMUX) + /* Enabling DMAMUX if present.*/ + if (bdma.allocated_mask != 0U) { + rccEnableDMAMUX(true); + } +#endif + + /* Enables the associated IRQ vector if not already enabled and if a + callback is defined.*/ + if (func != NULL) { + nvicEnableVector(stp->vector, priority); + } + + /* Putting the stream in a known state.*/ + bdmaStreamDisable(stp); + stp->channel->CCR = STM32_BDMA_CR_RESET_VALUE; + + return stp; + } + } + + return NULL; +} + +/** + * @brief Allocates a BDMA stream. + * @details The stream is allocated and, if required, the BDMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific stream or: + * - @p STM32_BDMA_STREAM_ID_ANY for any stream. + * . + * @param[in] priority IRQ priority for the BDMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_bdma_stream_t + * structure. + * @retval NULL if a/the stream is not available. + * + * @api + */ +const stm32_bdma_stream_t *bdmaStreamAlloc(uint32_t id, + uint32_t priority, + stm32_bdmaisr_t func, + void *param) { + const stm32_bdma_stream_t *stp; + + osalSysLock(); + stp = bdmaStreamAllocI(id, priority, func, param); + osalSysUnlock(); + + return stp; +} + +/** + * @brief Releases a BDMA stream. + * @details The stream is freed and, if required, the BDMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * + * @iclass + */ +void bdmaStreamFreeI(const stm32_bdma_stream_t *stp) { + + osalDbgCheck(stp != NULL); + + /* Check if the streams is not taken.*/ + osalDbgAssert((bdma.allocated_mask & (1U << stp->selfindex)) != 0U, + "not allocated"); + + /* Disables the associated IRQ vector.*/ + nvicDisableVector(stp->vector); + + /* Marks the stream as not allocated.*/ + bdma.allocated_mask &= ~(1U << stp->selfindex); + + /* Clearing associated handler and parameter.*/ + bdma.streams->func = NULL; + bdma.streams->param = NULL; + + /* Shutting down clocks that are no more required, if any.*/ + if ((bdma.allocated_mask & STM32_BDMA_STREAMS_MASK) == 0U) { + rccDisableBDMA1(); + } +} + +/** + * @brief Releases a BDMA stream. + * @details The stream is freed and, if required, the BDMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * + * @api + */ +void bdmaStreamFree(const stm32_bdma_stream_t *stp) { + + osalSysLock(); + bdmaStreamFreeI(stp); + osalSysUnlock(); +} + +/** + * @brief Associates a peripheral request to a BDMA stream. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] stp pointer to a @p stm32_bdma_stream_t structure + * @param[in] per peripheral identifier + * + * @special + */ +void bdmaSetRequestSource(const stm32_bdma_stream_t *stp, uint32_t per) { + + osalDbgCheck(per < 256U); + + stp->mux->CCR = per; +} + +#endif /* STM32_BDMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h b/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h index 6ed63f11c0..3e13f2772e 100644 --- a/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h +++ b/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h @@ -1,441 +1,441 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file BDMAv1/stm32_bdma.h - * @brief BDMA helper driver header. - * @note This driver uses the new naming convention used for the STM32F2xx - * so the "BDMA channels" are referred as "BDMA streams". - * - * @addtogroup STM32_BDMA - * @{ - */ - -#ifndef STM32_BDMA_H -#define STM32_BDMA_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Total number of BDMA streams. - * @details This is the total number of streams among all the BDMA units. - */ -#define STM32_BDMA_STREAMS 8U - -/** - * @brief Mask of the ISR bits passed to the BDMA callback functions. - */ -#define STM32_BDMA_ISR_MASK 0x0EU - -/** - * @brief Checks if a BDMA priority is within the valid range. - * - * @param[in] prio BDMA priority - * @retval The check result. - * @retval false invalid BDMA priority. - * @retval true correct BDMA priority. - */ -#define STM32_BDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) - -/** - * @brief Checks if a BDMA stream id is within the valid range. - * - * @param[in] id BDMA stream id - * @retval The check result. - * @retval false invalid DMA stream. - * @retval true correct DMA stream. - */ -#define STM32_BDMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) <= STM32_BDMA_STREAMS)) - -/** - * @name Special stream identifiers - * @{ - */ -#define STM32_BDMA_STREAM_ID_ANY STM32_BDMA_STREAMS -/** @} */ - -/** - * @name BDMA streams identifiers - * @{ - */ -/** - * @brief Returns a pointer to a stm32_dma_stream_t structure. - * - * @param[in] id the stream numeric identifier - * @return A pointer to the stm32_bdma_stream_t constant structure - * associated to the BDMA stream. - */ -#define STM32_BDMA_STREAM(id) (&_stm32_bdma_streams[id]) - -#define STM32_BDMA1_STREAM0 STM32_BDMA_STREAM(0) -#define STM32_BDMA1_STREAM1 STM32_BDMA_STREAM(1) -#define STM32_BDMA1_STREAM2 STM32_BDMA_STREAM(2) -#define STM32_BDMA1_STREAM3 STM32_BDMA_STREAM(3) -#define STM32_BDMA1_STREAM4 STM32_BDMA_STREAM(4) -#define STM32_BDMA1_STREAM5 STM32_BDMA_STREAM(5) -#define STM32_BDMA1_STREAM6 STM32_BDMA_STREAM(6) -#define STM32_BDMA1_STREAM7 STM32_BDMA_STREAM(7) -/** @} */ - -/** - * @name CR register constants - * @{ - */ -#define STM32_BDMA_CR_RESET_VALUE 0x00000000U -#define STM32_BDMA_CR_EN BDMA_CCR_EN_Msk -#define STM32_BDMA_CR_TCIE BDMA_CCR_TCIE -#define STM32_BDMA_CR_HTIE BDMA_CCR_HTIE -#define STM32_BDMA_CR_TEIE BDMA_CCR_TEIE -#define STM32_BDMA_CR_DIR_MASK (BDMA_CCR_DIR | BDMA_CCR_MEM2MEM) -#define STM32_BDMA_CR_DIR_P2M 0U -#define STM32_BDMA_CR_DIR_M2P BDMA_CCR_DIR -#define STM32_BDMA_CR_DIR_M2M BDMA_CCR_MEM2MEM -#define STM32_BDMA_CR_CIRC BDMA_CCR_CIRC -#define STM32_BDMA_CR_PINC BDMA_CCR_PINC -#define STM32_BDMA_CR_MINC BDMA_CCR_MINC -#define STM32_BDMA_CR_PSIZE_MASK BDMA_CCR_PSIZE_Msk -#define STM32_BDMA_CR_PSIZE_BYTE 0U -#define STM32_BDMA_CR_PSIZE_HWORD BDMA_CCR_PSIZE_0 -#define STM32_BDMA_CR_PSIZE_WORD BDMA_CCR_PSIZE_1 -#define STM32_BDMA_CR_MSIZE_MASK BDMA_CCR_MSIZE_Msk -#define STM32_BDMA_CR_MSIZE_BYTE 0U -#define STM32_BDMA_CR_MSIZE_HWORD BDMA_CCR_MSIZE_0 -#define STM32_BDMA_CR_MSIZE_WORD BDMA_CCR_MSIZE_1 -#define STM32_BDMA_CR_SIZE_MASK (STM32_BDMA_CR_PSIZE_MASK | \ - STM32_BDMA_CR_MSIZE_MASK) -#define STM32_BDMA_CR_PL_MASK BDMA_CCR_PL_Msk -#define STM32_BDMA_CR_PL(n) ((n) << 12U) -#if !defined(STM32_ENFORCE_H7_REV_XY) -#define STM32_BDMA_CR_DBM BDMA_CCR_DBM -#define STM32_BDMA_CR_CM BDMA_CCR_CT -#endif -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - * @{ - */ -#define STM32_BDMA_ISR_TEIF BDMA_ISR_TEIF0 -#define STM32_BDMA_ISR_HTIF BDMA_ISR_HTIF0 -#define STM32_BDMA_ISR_TCIF BDMA_ISR_TCIF0 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_BDMA1) -#error "STM32_HAS_BDMA1 missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH0_HANDLER) -#error "STM32_BDMA1_CH0_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH1_HANDLER) -#error "STM32_BDMA1_CH1_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH2_HANDLER) -#error "STM32_BDMA1_CH2_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH3_HANDLER) -#error "STM32_BDMA1_CH3_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH4_HANDLER) -#error "STM32_BDMA1_CH4_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH5_HANDLER) -#error "STM32_BDMA1_CH5_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH6_HANDLER) -#error "STM32_BDMA1_CH6_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH7_HANDLER) -#error "STM32_BDMA1_CH7_HANDLER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH0_NUMBER) -#error "STM32_BDMA1_CH0_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH1_NUMBER) -#error "STM32_BDMA1_CH1_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH2_NUMBER) -#error "STM32_BDMA1_CH2_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH3_NUMBER) -#error "STM32_BDMA1_CH3_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH4_NUMBER) -#error "STM32_BDMA1_CH4_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH5_NUMBER) -#error "STM32_BDMA1_CH5_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH6_NUMBER) -#error "STM32_BDMA1_CH6_NUMBER missing in registry" -#endif - -#if !defined(STM32_BDMA1_CH7_NUMBER) -#error "STM32_BDMA1_CH7_NUMBER missing in registry" -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 BDMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the ISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_bdmaisr_t)(void *p, uint32_t flags); - -/** - * @brief STM32 BDMA stream descriptor structure. - */ -typedef struct { - BDMA_TypeDef *bdma; /**< @brief Associated BDMA. */ - BDMA_Channel_TypeDef *channel; /**< @brief Associated BDMA channel.*/ - uint8_t shift; /**< @brief Bit offset in ISR and - IFCR registers. */ - DMAMUX_Channel_TypeDef *mux; /**< @brief Associated BDMA stream. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_bdma_stream_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Associates a peripheral data register to a BDMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * @param[in] addr value to be written in the CPAR register - * - * @special - */ -#define bdmaStreamSetPeripheral(stp, addr) { \ - (stp)->channel->CPAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a BDMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * @param[in] addr value to be written in the CMAR register - * - * @special - */ -#define bdmaStreamSetMemory(stp, addr) { \ - (stp)->channel->CM0AR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define bdmaStreamSetTransactionSize(stp, size) { \ - (stp)->channel->CNDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define bdmaStreamGetTransactionSize(stp) ((size_t)((stp)->channel->CNDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * @param[in] mode value to be written in the CCR register - * - * @special - */ -#define bdmaStreamSetMode(stp, mode) { \ - (stp)->channel->CCR = (uint32_t)(mode); \ -} - -/** - * @brief BDMA stream enable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * - * @special - */ -#define bdmaStreamEnable(stp) { \ - (stp)->channel->CCR |= STM32_BDMA_CR_EN; \ -} - -/** - * @brief BDMA stream disable. - * @details The function disables the specified stream and then clears any - * pending interrupt. - * @note This function can be invoked in both ISR or thread context. - * @note Interrupts enabling flags are set to zero after this call, see - * bug 3607518. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * - * @special - */ -#define bdmaStreamDisable(stp) { \ - (stp)->channel->CCR &= ~(STM32_BDMA_CR_TCIE | STM32_BDMA_CR_HTIE | \ - STM32_BDMA_CR_TEIE | STM32_BDMA_CR_EN); \ - bdmaStreamClearInterrupt(stp); \ -} - -/** - * @brief BDMA 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 bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * - * @special - */ -#define bdmaStreamClearInterrupt(stp) { \ - (stp)->bdma->IFCR = STM32_BDMA_ISR_MASK << (stp)->shift; \ -} - -/** - * @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 bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - * @param[in] mode value to be written in the CCR register, this value - * is implicitly ORed with: - * - @p STM32_BDMA_CR_MINC - * - @p STM32_BDMA_CR_PINC - * - @p STM32_BDMA_CR_DIR_M2M - * - @p STM32_BDMA_CR_EN - * . - * @param[in] src source address - * @param[in] dst destination address - * @param[in] n number of data units to copy - */ -#define bdmaStartMemCopy(stp, mode, src, dst, n) { \ - bdmaStreamSetPeripheral(stp, src); \ - bdmaStreamSetMemory0(stp, dst); \ - bdmaStreamSetTransactionSize(stp, n); \ - bdmaStreamSetMode(stp, (mode) | \ - STM32_BDMA_CR_MINC | STM32_BDMA_CR_PINC | \ - STM32_BDMA_CR_DIR_M2M | STM32_BDMA_CR_EN); \ -} - -/** - * @brief Polled wait for BDMA transfer end. - * @pre The stream must have been allocated using @p bdmaStreamAllocate(). - * @post After use the stream can be released using @p bdmaStreamRelease(). - * - * @param[in] stp pointer to an @p stm32_bdma_stream_t structure - */ -#define bdmaWaitCompletion(stp) { \ - while ((stp)->channel->CNDTR > 0U) \ - ; \ - bdmaStreamDisable(stp); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_bdma_stream_t _stm32_bdma_streams[STM32_BDMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void bdmaInit(void); - const stm32_bdma_stream_t *bdmaStreamAllocI(uint32_t id, - uint32_t priority, - stm32_bdmaisr_t func, - void *param); - const stm32_bdma_stream_t *bdmaStreamAlloc(uint32_t id, - uint32_t priority, - stm32_bdmaisr_t func, - void *param); - void bdmaStreamFreeI(const stm32_bdma_stream_t *stp); - void bdmaStreamFree(const stm32_bdma_stream_t *stp); - void bdmaSetRequestSource(const stm32_bdma_stream_t *stp, uint32_t per); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_BDMA_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file BDMAv1/stm32_bdma.h + * @brief BDMA helper driver header. + * @note This driver uses the new naming convention used for the STM32F2xx + * so the "BDMA channels" are referred as "BDMA streams". + * + * @addtogroup STM32_BDMA + * @{ + */ + +#ifndef STM32_BDMA_H +#define STM32_BDMA_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of BDMA streams. + * @details This is the total number of streams among all the BDMA units. + */ +#define STM32_BDMA_STREAMS 8U + +/** + * @brief Mask of the ISR bits passed to the BDMA callback functions. + */ +#define STM32_BDMA_ISR_MASK 0x0EU + +/** + * @brief Checks if a BDMA priority is within the valid range. + * + * @param[in] prio BDMA priority + * @retval The check result. + * @retval false invalid BDMA priority. + * @retval true correct BDMA priority. + */ +#define STM32_BDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) + +/** + * @brief Checks if a BDMA stream id is within the valid range. + * + * @param[in] id BDMA stream id + * @retval The check result. + * @retval false invalid DMA stream. + * @retval true correct DMA stream. + */ +#define STM32_BDMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) <= STM32_BDMA_STREAMS)) + +/** + * @name Special stream identifiers + * @{ + */ +#define STM32_BDMA_STREAM_ID_ANY STM32_BDMA_STREAMS +/** @} */ + +/** + * @name BDMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_dma_stream_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_bdma_stream_t constant structure + * associated to the BDMA stream. + */ +#define STM32_BDMA_STREAM(id) (&_stm32_bdma_streams[id]) + +#define STM32_BDMA1_STREAM0 STM32_BDMA_STREAM(0) +#define STM32_BDMA1_STREAM1 STM32_BDMA_STREAM(1) +#define STM32_BDMA1_STREAM2 STM32_BDMA_STREAM(2) +#define STM32_BDMA1_STREAM3 STM32_BDMA_STREAM(3) +#define STM32_BDMA1_STREAM4 STM32_BDMA_STREAM(4) +#define STM32_BDMA1_STREAM5 STM32_BDMA_STREAM(5) +#define STM32_BDMA1_STREAM6 STM32_BDMA_STREAM(6) +#define STM32_BDMA1_STREAM7 STM32_BDMA_STREAM(7) +/** @} */ + +/** + * @name CR register constants + * @{ + */ +#define STM32_BDMA_CR_RESET_VALUE 0x00000000U +#define STM32_BDMA_CR_EN BDMA_CCR_EN_Msk +#define STM32_BDMA_CR_TCIE BDMA_CCR_TCIE +#define STM32_BDMA_CR_HTIE BDMA_CCR_HTIE +#define STM32_BDMA_CR_TEIE BDMA_CCR_TEIE +#define STM32_BDMA_CR_DIR_MASK (BDMA_CCR_DIR | BDMA_CCR_MEM2MEM) +#define STM32_BDMA_CR_DIR_P2M 0U +#define STM32_BDMA_CR_DIR_M2P BDMA_CCR_DIR +#define STM32_BDMA_CR_DIR_M2M BDMA_CCR_MEM2MEM +#define STM32_BDMA_CR_CIRC BDMA_CCR_CIRC +#define STM32_BDMA_CR_PINC BDMA_CCR_PINC +#define STM32_BDMA_CR_MINC BDMA_CCR_MINC +#define STM32_BDMA_CR_PSIZE_MASK BDMA_CCR_PSIZE_Msk +#define STM32_BDMA_CR_PSIZE_BYTE 0U +#define STM32_BDMA_CR_PSIZE_HWORD BDMA_CCR_PSIZE_0 +#define STM32_BDMA_CR_PSIZE_WORD BDMA_CCR_PSIZE_1 +#define STM32_BDMA_CR_MSIZE_MASK BDMA_CCR_MSIZE_Msk +#define STM32_BDMA_CR_MSIZE_BYTE 0U +#define STM32_BDMA_CR_MSIZE_HWORD BDMA_CCR_MSIZE_0 +#define STM32_BDMA_CR_MSIZE_WORD BDMA_CCR_MSIZE_1 +#define STM32_BDMA_CR_SIZE_MASK (STM32_BDMA_CR_PSIZE_MASK | \ + STM32_BDMA_CR_MSIZE_MASK) +#define STM32_BDMA_CR_PL_MASK BDMA_CCR_PL_Msk +#define STM32_BDMA_CR_PL(n) ((n) << 12U) +#if !defined(STM32_ENFORCE_H7_REV_XY) +#define STM32_BDMA_CR_DBM BDMA_CCR_DBM +#define STM32_BDMA_CR_CM BDMA_CCR_CT +#endif +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + * @{ + */ +#define STM32_BDMA_ISR_TEIF BDMA_ISR_TEIF0 +#define STM32_BDMA_ISR_HTIF BDMA_ISR_HTIF0 +#define STM32_BDMA_ISR_TCIF BDMA_ISR_TCIF0 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_BDMA1) +#error "STM32_HAS_BDMA1 missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH0_HANDLER) +#error "STM32_BDMA1_CH0_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH1_HANDLER) +#error "STM32_BDMA1_CH1_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH2_HANDLER) +#error "STM32_BDMA1_CH2_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH3_HANDLER) +#error "STM32_BDMA1_CH3_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH4_HANDLER) +#error "STM32_BDMA1_CH4_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH5_HANDLER) +#error "STM32_BDMA1_CH5_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH6_HANDLER) +#error "STM32_BDMA1_CH6_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH7_HANDLER) +#error "STM32_BDMA1_CH7_HANDLER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH0_NUMBER) +#error "STM32_BDMA1_CH0_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH1_NUMBER) +#error "STM32_BDMA1_CH1_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH2_NUMBER) +#error "STM32_BDMA1_CH2_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH3_NUMBER) +#error "STM32_BDMA1_CH3_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH4_NUMBER) +#error "STM32_BDMA1_CH4_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH5_NUMBER) +#error "STM32_BDMA1_CH5_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH6_NUMBER) +#error "STM32_BDMA1_CH6_NUMBER missing in registry" +#endif + +#if !defined(STM32_BDMA1_CH7_NUMBER) +#error "STM32_BDMA1_CH7_NUMBER missing in registry" +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 BDMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the ISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_bdmaisr_t)(void *p, uint32_t flags); + +/** + * @brief STM32 BDMA stream descriptor structure. + */ +typedef struct { + BDMA_TypeDef *bdma; /**< @brief Associated BDMA. */ + BDMA_Channel_TypeDef *channel; /**< @brief Associated BDMA channel.*/ + uint8_t shift; /**< @brief Bit offset in ISR and + IFCR registers. */ + DMAMUX_Channel_TypeDef *mux; /**< @brief Associated BDMA stream. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_bdma_stream_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Associates a peripheral data register to a BDMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * @param[in] addr value to be written in the CPAR register + * + * @special + */ +#define bdmaStreamSetPeripheral(stp, addr) { \ + (stp)->channel->CPAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a BDMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * @param[in] addr value to be written in the CMAR register + * + * @special + */ +#define bdmaStreamSetMemory(stp, addr) { \ + (stp)->channel->CM0AR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define bdmaStreamSetTransactionSize(stp, size) { \ + (stp)->channel->CNDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define bdmaStreamGetTransactionSize(stp) ((size_t)((stp)->channel->CNDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * @param[in] mode value to be written in the CCR register + * + * @special + */ +#define bdmaStreamSetMode(stp, mode) { \ + (stp)->channel->CCR = (uint32_t)(mode); \ +} + +/** + * @brief BDMA stream enable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * + * @special + */ +#define bdmaStreamEnable(stp) { \ + (stp)->channel->CCR |= STM32_BDMA_CR_EN; \ +} + +/** + * @brief BDMA stream disable. + * @details The function disables the specified stream and then clears any + * pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * + * @special + */ +#define bdmaStreamDisable(stp) { \ + (stp)->channel->CCR &= ~(STM32_BDMA_CR_TCIE | STM32_BDMA_CR_HTIE | \ + STM32_BDMA_CR_TEIE | STM32_BDMA_CR_EN); \ + bdmaStreamClearInterrupt(stp); \ +} + +/** + * @brief BDMA 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 bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * + * @special + */ +#define bdmaStreamClearInterrupt(stp) { \ + (stp)->bdma->IFCR = STM32_BDMA_ISR_MASK << (stp)->shift; \ +} + +/** + * @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 bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + * @param[in] mode value to be written in the CCR register, this value + * is implicitly ORed with: + * - @p STM32_BDMA_CR_MINC + * - @p STM32_BDMA_CR_PINC + * - @p STM32_BDMA_CR_DIR_M2M + * - @p STM32_BDMA_CR_EN + * . + * @param[in] src source address + * @param[in] dst destination address + * @param[in] n number of data units to copy + */ +#define bdmaStartMemCopy(stp, mode, src, dst, n) { \ + bdmaStreamSetPeripheral(stp, src); \ + bdmaStreamSetMemory0(stp, dst); \ + bdmaStreamSetTransactionSize(stp, n); \ + bdmaStreamSetMode(stp, (mode) | \ + STM32_BDMA_CR_MINC | STM32_BDMA_CR_PINC | \ + STM32_BDMA_CR_DIR_M2M | STM32_BDMA_CR_EN); \ +} + +/** + * @brief Polled wait for BDMA transfer end. + * @pre The stream must have been allocated using @p bdmaStreamAllocate(). + * @post After use the stream can be released using @p bdmaStreamRelease(). + * + * @param[in] stp pointer to an @p stm32_bdma_stream_t structure + */ +#define bdmaWaitCompletion(stp) { \ + while ((stp)->channel->CNDTR > 0U) \ + ; \ + bdmaStreamDisable(stp); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_bdma_stream_t _stm32_bdma_streams[STM32_BDMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void bdmaInit(void); + const stm32_bdma_stream_t *bdmaStreamAllocI(uint32_t id, + uint32_t priority, + stm32_bdmaisr_t func, + void *param); + const stm32_bdma_stream_t *bdmaStreamAlloc(uint32_t id, + uint32_t priority, + stm32_bdmaisr_t func, + void *param); + void bdmaStreamFreeI(const stm32_bdma_stream_t *stp); + void bdmaStreamFree(const stm32_bdma_stream_t *stp); + void bdmaSetRequestSource(const stm32_bdma_stream_t *stp, uint32_t per); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_BDMA_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/CANv1/driver.mk b/os/hal/ports/STM32/LLD/CANv1/driver.mk index 608a9273f2..6db597adb8 100644 --- a/os/hal/ports/STM32/LLD/CANv1/driver.mk +++ b/os/hal/ports/STM32/LLD/CANv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1 diff --git a/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c b/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c index 5e24fa1d4d..e76fa42af3 100644 --- a/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c +++ b/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c @@ -1,1049 +1,1049 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file CANv1/hal_can_lld.c - * @brief STM32 CAN subsystem low level driver source. - * - * @addtogroup CAN - * @{ - */ - -#include "hal.h" - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* - * Addressing differences in the headers, they seem unable to agree on names. - */ -#if STM32_CAN_USE_CAN1 -#if !defined(CAN1) -#define CAN1 CAN -#endif -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief CAN1 driver identifier.*/ -#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) -CANDriver CAND1; -#endif - -/** @brief CAN2 driver identifier.*/ -#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) -CANDriver CAND2; -#endif - -/** @brief CAN3 driver identifier.*/ -#if STM32_CAN_USE_CAN3 || defined(__DOXYGEN__) -CANDriver CAND3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ -/** - * @brief Programs the filters of CAN 1 and CAN 2. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] can2sb number of the first filter assigned to CAN2 - * @param[in] num number of entries in the filters array, if zero then - * a default filter is programmed - * @param[in] cfp pointer to the filters array, can be @p NULL if - * (num == 0) - * - * @notapi - */ -static void can_lld_set_filters(CANDriver* canp, - uint32_t can2sb, - uint32_t num, - const CANFilter *cfp) { - -#if STM32_CAN_USE_CAN2 - if (canp == &CAND2) { - /* Set handle to CAN1, because CAN1 manages the filters of CAN2.*/ - canp = &CAND1; - } -#endif - - /* Temporarily enabling CAN clock.*/ -#if STM32_CAN_USE_CAN1 - if (canp == &CAND1) { - rccEnableCAN1(true); - /* Filters initialization.*/ - canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | CAN_FMR_FINIT; - canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | (can2sb << 8) | CAN_FMR_FINIT; - } -#endif - -#if STM32_CAN_USE_CAN3 - if (canp == &CAND3) { - rccEnableCAN3(true); - /* Filters initialization.*/ - canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | CAN_FMR_FINIT; - } -#endif - - if (num > 0) { - uint32_t i, fmask; - - /* All filters cleared.*/ - canp->can->FA1R = 0; - canp->can->FM1R = 0; - canp->can->FS1R = 0; - canp->can->FFA1R = 0; - -#if STM32_CAN_USE_CAN1 - if (canp == &CAND1) { - for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) { - canp->can->sFilterRegister[i].FR1 = 0; - canp->can->sFilterRegister[i].FR2 = 0; - } - } -#endif - -#if STM32_CAN_USE_CAN3 - if (canp == &CAND3) { - for (i = 0; i < STM32_CAN3_MAX_FILTERS; i++) { - canp->can->sFilterRegister[i].FR1 = 0; - canp->can->sFilterRegister[i].FR2 = 0; - } - } -#endif - - /* Scanning the filters array.*/ - for (i = 0; i < num; i++) { - fmask = 1 << cfp->filter; - if (cfp->mode) - canp->can->FM1R |= fmask; - if (cfp->scale) - canp->can->FS1R |= fmask; - if (cfp->assignment) - canp->can->FFA1R |= fmask; - canp->can->sFilterRegister[cfp->filter].FR1 = cfp->register1; - canp->can->sFilterRegister[cfp->filter].FR2 = cfp->register2; - canp->can->FA1R |= fmask; - cfp++; - } - } - else { - /* Setting up a single default filter that enables everything for both - CANs.*/ - canp->can->sFilterRegister[0].FR1 = 0; - canp->can->sFilterRegister[0].FR2 = 0; -#if STM32_CAN_USE_CAN2 - if (canp == &CAND1) { - canp->can->sFilterRegister[can2sb].FR1 = 0; - canp->can->sFilterRegister[can2sb].FR2 = 0; - } -#endif - canp->can->FM1R = 0; - canp->can->FFA1R = 0; - canp->can->FS1R = 1; - canp->can->FA1R = 1; -#if STM32_CAN_USE_CAN2 - if (canp == &CAND1) { - canp->can->FS1R |= 1 << can2sb; - canp->can->FA1R |= 1 << can2sb; - } -#endif - } - canp->can->FMR &= ~CAN_FMR_FINIT; - - /* Clock disabled, it will be enabled again in can_lld_start().*/ - /* Temporarily enabling CAN clock.*/ -#if STM32_CAN_USE_CAN1 - if (canp == &CAND1) { - rccDisableCAN1(); - } -#endif -#if STM32_CAN_USE_CAN3 - if (canp == &CAND3) { - rccDisableCAN3(); - } -#endif -} - -/** - * @brief Common TX ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_tx_handler(CANDriver *canp) { - uint32_t tsr; - eventflags_t flags; - - /* Clearing IRQ sources.*/ - tsr = canp->can->TSR; - canp->can->TSR = tsr; - - /* Flags to be signaled through the TX event source.*/ - flags = 0U; - - /* Checking mailbox 0.*/ - if ((tsr & CAN_TSR_RQCP0) != 0U) { - if ((tsr & (CAN_TSR_ALST0 | CAN_TSR_TERR0)) != 0U) { - flags |= CAN_MAILBOX_TO_MASK(1U) << 16U; - } - else { - flags |= CAN_MAILBOX_TO_MASK(1U); - } - } - - /* Checking mailbox 1.*/ - if ((tsr & CAN_TSR_RQCP1) != 0U) { - if ((tsr & (CAN_TSR_ALST1 | CAN_TSR_TERR1)) != 0U) { - flags |= CAN_MAILBOX_TO_MASK(2U) << 16U; - } - else { - flags |= CAN_MAILBOX_TO_MASK(2U); - } - } - - /* Checking mailbox 2.*/ - if ((tsr & CAN_TSR_RQCP2) != 0U) { - if ((tsr & (CAN_TSR_ALST2 | CAN_TSR_TERR2)) != 0U) { - flags |= CAN_MAILBOX_TO_MASK(3U) << 16U; - } - else { - flags |= CAN_MAILBOX_TO_MASK(3U); - } - } - - /* Signaling flags and waking up threads waiting for a transmission slot.*/ - _can_tx_empty_isr(canp, flags); -} - -/** - * @brief Common RX0 ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_rx0_handler(CANDriver *canp) { - uint32_t rf0r; - - rf0r = canp->can->RF0R; - if ((rf0r & CAN_RF0R_FMP0) > 0) { - /* No more receive events until the queue 0 has been emptied.*/ - canp->can->IER &= ~CAN_IER_FMPIE0; - _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(1U)); - } - if ((rf0r & CAN_RF0R_FOVR0) > 0) { - /* Overflow events handling.*/ - canp->can->RF0R = CAN_RF0R_FOVR0; - _can_error_isr(canp, CAN_OVERFLOW_ERROR); - } -} - -/** - * @brief Common RX1 ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_rx1_handler(CANDriver *canp) { - uint32_t rf1r; - - rf1r = canp->can->RF1R; - if ((rf1r & CAN_RF1R_FMP1) > 0) { - /* No more receive events until the queue 0 has been emptied.*/ - canp->can->IER &= ~CAN_IER_FMPIE1; - _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(2U)); - } - if ((rf1r & CAN_RF1R_FOVR1) > 0) { - /* Overflow events handling.*/ - canp->can->RF1R = CAN_RF1R_FOVR1; - _can_error_isr(canp, CAN_OVERFLOW_ERROR); - } -} - -/** - * @brief Common SCE ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_sce_handler(CANDriver *canp) { - uint32_t msr; - - /* Clearing IRQ sources.*/ - msr = canp->can->MSR; - canp->can->MSR = msr; - - /* Wakeup event.*/ -#if CAN_USE_SLEEP_MODE - if (msr & CAN_MSR_WKUI) { - canp->state = CAN_READY; - canp->can->MCR &= ~CAN_MCR_SLEEP; - _can_wakeup_isr(canp); - } -#endif /* CAN_USE_SLEEP_MODE */ - /* Error event.*/ - if (msr & CAN_MSR_ERRI) { - eventflags_t flags; - uint32_t esr = canp->can->ESR; - -#if STM32_CAN_REPORT_ALL_ERRORS - flags = (eventflags_t)(esr & 7); - if ((esr & CAN_ESR_LEC) > 0) - flags |= CAN_FRAMING_ERROR; -#else - flags = 0; -#endif - - /* The content of the ESR register is copied unchanged in the upper - half word of the listener flags mask.*/ - _can_error_isr(canp, flags | (eventflags_t)(esr << 16U)); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) -#if defined(STM32_CAN1_UNIFIED_HANDLER) -/** - * @brief CAN1 unified interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_UNIFIED_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND1); - can_lld_rx0_handler(&CAND1); - can_lld_rx1_handler(&CAND1); - can_lld_sce_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} -#else /* !defined(STM32_CAN1_UNIFIED_HANDLER) */ - -#if !defined(STM32_CAN1_TX_HANDLER) -#error "STM32_CAN1_TX_HANDLER not defined" -#endif -#if !defined(STM32_CAN1_RX0_HANDLER) -#error "STM32_CAN1_RX0_HANDLER not defined" -#endif -#if !defined(STM32_CAN1_RX1_HANDLER) -#error "STM32_CAN1_RX1_HANDLER not defined" -#endif -#if !defined(STM32_CAN1_SCE_HANDLER) -#error "STM32_CAN1_SCE_HANDLER not defined" -#endif - -/** - * @brief CAN1 TX interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 RX0 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx0_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 RX1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx1_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 SCE interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_sce_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_CAN1_UNIFIED_HANDLER) */ -#endif /* STM32_CAN_USE_CAN1 */ - -#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) -#if defined(STM32_CAN2_UNIFIED_HANDLER) -/** - * @brief CAN1 unified interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_UNIFIED_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND2); - can_lld_rx0_handler(&CAND2); - can_lld_rx1_handler(&CAND2); - can_lld_sce_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} -#else /* !defined(STM32_CAN2_UNIFIED_HANDLER) */ - -#if !defined(STM32_CAN1_TX_HANDLER) -#error "STM32_CAN1_TX_HANDLER not defined" -#endif -#if !defined(STM32_CAN1_RX0_HANDLER) -#error "STM32_CAN1_RX0_HANDLER not defined" -#endif -#if !defined(STM32_CAN1_RX1_HANDLER) -#error "STM32_CAN1_RX1_HANDLER not defined" -#endif -#if !defined(STM32_CAN1_SCE_HANDLER) -#error "STM32_CAN1_SCE_HANDLER not defined" -#endif - -/** - * @brief CAN2 TX interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_TX_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN2 RX0 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_RX0_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx0_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN2 RX1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_RX1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx1_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN2 SCE interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_SCE_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_sce_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_CAN2_UNIFIED_HANDLER) */ -#endif /* STM32_CAN_USE_CAN2 */ - -#if STM32_CAN_USE_CAN3 || defined(__DOXYGEN__) -#if defined(STM32_CAN3_UNIFIED_HANDLER) -/** - * @brief CAN1 unified interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN3_UNIFIED_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND3); - can_lld_rx0_handler(&CAND3); - can_lld_rx1_handler(&CAND3); - can_lld_sce_handler(&CAND3); - - OSAL_IRQ_EPILOGUE(); -} -#else /* !defined(STM32_CAN3_UNIFIED_HANDLER) */ - -#if !defined(STM32_CAN3_TX_HANDLER) -#error "STM32_CAN3_TX_HANDLER not defined" -#endif -#if !defined(STM32_CAN3_RX0_HANDLER) -#error "STM32_CAN3_RX0_HANDLER not defined" -#endif -#if !defined(STM32_CAN3_RX1_HANDLER) -#error "STM32_CAN3_RX1_HANDLER not defined" -#endif -#if !defined(STM32_CAN3_SCE_HANDLER) -#error "STM32_CAN3_SCE_HANDLER not defined" -#endif - -/** - * @brief CAN3 TX interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN3_TX_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN3 RX0 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN3_RX0_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx0_handler(&CAND3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 RX3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN3_RX1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx1_handler(&CAND3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 SCE interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN3_SCE_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_sce_handler(&CAND3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_CAN1_UNIFIED_HANDLER) */ -#endif /* STM32_CAN_USE_CAN1 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level CAN driver initialization. - * - * @notapi - */ -void can_lld_init(void) { - -#if STM32_CAN_USE_CAN1 - /* Driver initialization.*/ - canObjectInit(&CAND1); - CAND1.can = CAN1; -#if defined(STM32_CAN1_UNIFIED_NUMBER) - nvicEnableVector(STM32_CAN1_UNIFIED_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); -#else - nvicEnableVector(STM32_CAN1_TX_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN1_RX0_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN1_RX1_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN1_SCE_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); -#endif -#endif - -#if STM32_CAN_USE_CAN2 - /* Driver initialization.*/ - canObjectInit(&CAND2); - CAND2.can = CAN2; -#if defined(STM32_CAN2_UNIFIED_NUMBER) - nvicEnableVector(STM32_CAN2_UNIFIED_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); -#else - nvicEnableVector(STM32_CAN2_TX_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN2_RX0_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN2_RX1_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN2_SCE_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); -#endif -#endif - -#if STM32_CAN_USE_CAN3 - /* Driver initialization.*/ - canObjectInit(&CAND3); - CAND3.can = CAN3; -#if defined(STM32_CAN3_UNIFIED_NUMBER) - nvicEnableVector(STM32_CAN3_UNIFIED_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); -#else - nvicEnableVector(STM32_CAN3_TX_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN3_RX0_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN3_RX1_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN3_SCE_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); -#endif -#endif - - /* Filters initialization.*/ -#if STM32_CAN_USE_CAN1 -#if STM32_HAS_CAN2 - can_lld_set_filters(&CAND1, STM32_CAN_MAX_FILTERS / 2, 0, NULL); -#else - can_lld_set_filters(&CAND1, STM32_CAN_MAX_FILTERS, 0, NULL); -#endif -#endif - -#if STM32_HAS_CAN3 -#if STM32_CAN_USE_CAN3 - can_lld_set_filters(&CAND3, STM32_CAN3_MAX_FILTERS, 0, NULL); -#endif -#endif -} - -/** - * @brief Configures and activates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_start(CANDriver *canp) { - - /* Clock activation.*/ -#if STM32_CAN_USE_CAN1 - if (&CAND1 == canp) { - rccEnableCAN1(true); - } -#endif - -#if STM32_CAN_USE_CAN2 - if (&CAND2 == canp) { - rccEnableCAN1(true); /* CAN 2 requires CAN1, so enabling it first.*/ - rccEnableCAN2(true); - } -#endif - -#if STM32_CAN_USE_CAN3 - if (&CAND3 == canp) { - rccEnableCAN3(true); - } -#endif - - /* Configuring CAN. */ - canp->can->MCR = CAN_MCR_INRQ; - while ((canp->can->MSR & CAN_MSR_INAK) == 0) - osalThreadSleepS(1); - canp->can->BTR = canp->config->btr; - canp->can->MCR = canp->config->mcr; - - /* Interrupt sources initialization.*/ -#if STM32_CAN_REPORT_ALL_ERRORS - canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 | - CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE | - CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | - CAN_IER_FOVIE0 | CAN_IER_FOVIE1; -#else - canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 | - CAN_IER_WKUIE | CAN_IER_ERRIE | - CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | - CAN_IER_FOVIE0 | CAN_IER_FOVIE1; -#endif -} - -/** - * @brief Deactivates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_stop(CANDriver *canp) { - - /* If in ready state then disables the CAN peripheral.*/ - if (canp->state == CAN_READY) { -#if STM32_CAN_USE_CAN1 - if (&CAND1 == canp) { - CAN1->MCR = 0x00010002; /* Register reset value. */ - CAN1->IER = 0x00000000; /* All sources disabled. */ -#if STM32_CAN_USE_CAN2 - /* If CAND2 is stopped then CAN1 clock is stopped here.*/ - if (CAND2.state == CAN_STOP) -#endif - { - rccDisableCAN1(); - } - } -#endif - -#if STM32_CAN_USE_CAN2 - if (&CAND2 == canp) { - CAN2->MCR = 0x00010002; /* Register reset value. */ - CAN2->IER = 0x00000000; /* All sources disabled. */ -#if STM32_CAN_USE_CAN1 - /* If CAND1 is stopped then CAN1 clock is stopped here.*/ - if (CAND1.state == CAN_STOP) -#endif - { - rccDisableCAN1(); - } - rccDisableCAN2(); - } -#endif - -#if STM32_CAN_USE_CAN3 - if (&CAND3 == canp) { - CAN3->MCR = 0x00010002; /* Register reset value. */ - CAN3->IER = 0x00000000; /* All sources disabled. */ - rccDisableCAN3(); - } -#endif - } -} - -/** - * @brief Determines whether a frame can be transmitted. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @return The queue space availability. - * @retval false no space in the transmit queue. - * @retval true transmit slot available. - * - * @notapi - */ -bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { - - switch (mailbox) { - case CAN_ANY_MAILBOX: - return (canp->can->TSR & CAN_TSR_TME) != 0; - case 1: - return (canp->can->TSR & CAN_TSR_TME0) != 0; - case 2: - return (canp->can->TSR & CAN_TSR_TME1) != 0; - case 3: - return (canp->can->TSR & CAN_TSR_TME2) != 0; - default: - return false; - } -} - -/** - * @brief Inserts a frame into the transmit queue. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] ctfp pointer to the CAN frame to be transmitted - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @notapi - */ -void can_lld_transmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp) { - uint32_t tir; - CAN_TxMailBox_TypeDef *tmbp; - - /* Pointer to a free transmission mailbox.*/ - switch (mailbox) { - case CAN_ANY_MAILBOX: - if ((DBGMCU->IDCODE >> 16) == 0x1001) { - /* real STM32 */ - tmbp = &canp->can->sTxMailBox[(canp->can->TSR & CAN_TSR_CODE) >> 24]; - } else { - int n; - /* GD32 */ - if ((canp->can->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) - n = 0; - else if ((canp->can->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) - n = 1; - else if ((canp->can->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) - n = 2; - else { - /* silence? */ - return; - } - tmbp = &canp->can->sTxMailBox[n]; - } - break; - case 1: - tmbp = &canp->can->sTxMailBox[0]; - break; - case 2: - tmbp = &canp->can->sTxMailBox[1]; - break; - case 3: - tmbp = &canp->can->sTxMailBox[2]; - break; - default: - return; - } - - /* Preparing the message.*/ - if (ctfp->IDE) - tir = ((uint32_t)ctfp->EID << 3) | ((uint32_t)ctfp->RTR << 1) | - CAN_TI0R_IDE; - else - tir = ((uint32_t)ctfp->SID << 21) | ((uint32_t)ctfp->RTR << 1); - tmbp->TDTR = ctfp->DLC; - tmbp->TDLR = ctfp->data32[0]; - tmbp->TDHR = ctfp->data32[1]; - tmbp->TIR = tir | CAN_TI0R_TXRQ; -} - -/** - * @brief Determines whether a frame has been received. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @return The queue space availability. - * @retval false no space in the transmit queue. - * @retval true transmit slot available. - * - * @notapi - */ -bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { - - switch (mailbox) { - case CAN_ANY_MAILBOX: - return ((canp->can->RF0R & CAN_RF0R_FMP0) != 0 || - (canp->can->RF1R & CAN_RF1R_FMP1) != 0); - case 1: - return (canp->can->RF0R & CAN_RF0R_FMP0) != 0; - case 2: - return (canp->can->RF1R & CAN_RF1R_FMP1) != 0; - default: - return false; - } -} - -/** - * @brief Receives a frame from the input queue. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[out] crfp pointer to the buffer where the CAN frame is copied - * - * @notapi - */ -void can_lld_receive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp) { - uint32_t rir, rdtr; - - if (mailbox == CAN_ANY_MAILBOX) { - if ((canp->can->RF0R & CAN_RF0R_FMP0) != 0) - mailbox = 1; - else if ((canp->can->RF1R & CAN_RF1R_FMP1) != 0) - mailbox = 2; - else { - /* Should not happen, do nothing.*/ - return; - } - } - switch (mailbox) { - case 1: - /* Fetches the message.*/ - rir = canp->can->sFIFOMailBox[0].RIR; - rdtr = canp->can->sFIFOMailBox[0].RDTR; - crfp->data32[0] = canp->can->sFIFOMailBox[0].RDLR; - crfp->data32[1] = canp->can->sFIFOMailBox[0].RDHR; - - /* Releases the mailbox.*/ - canp->can->RF0R = CAN_RF0R_RFOM0; - - /* If the queue is empty re-enables the interrupt in order to generate - events again.*/ - if ((canp->can->RF0R & CAN_RF0R_FMP0) == 0) - canp->can->IER |= CAN_IER_FMPIE0; - break; - case 2: - /* Fetches the message.*/ - rir = canp->can->sFIFOMailBox[1].RIR; - rdtr = canp->can->sFIFOMailBox[1].RDTR; - crfp->data32[0] = canp->can->sFIFOMailBox[1].RDLR; - crfp->data32[1] = canp->can->sFIFOMailBox[1].RDHR; - - /* Releases the mailbox.*/ - canp->can->RF1R = CAN_RF1R_RFOM1; - - /* If the queue is empty re-enables the interrupt in order to generate - events again.*/ - if ((canp->can->RF1R & CAN_RF1R_FMP1) == 0) - canp->can->IER |= CAN_IER_FMPIE1; - break; - default: - /* Should not happen, do nothing.*/ - return; - } - - /* Decodes the various fields in the RX frame.*/ - crfp->RTR = (rir & CAN_RI0R_RTR) >> 1; - crfp->IDE = (rir & CAN_RI0R_IDE) >> 2; - if (crfp->IDE) - crfp->EID = rir >> 3; - else - crfp->SID = rir >> 21; - crfp->DLC = rdtr & CAN_RDT0R_DLC; - crfp->FMI = (uint8_t)(rdtr >> 8); - crfp->TIME = (uint16_t)(rdtr >> 16); -} - -/** - * @brief Tries to abort an ongoing transmission. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number - * - * @notapi - */ -void can_lld_abort(CANDriver *canp, - canmbx_t mailbox) { - - canp->can->TSR = 128U << ((mailbox - 1U) * 8U); -} - -#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) -/** - * @brief Enters the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_sleep(CANDriver *canp) { - - canp->can->MCR |= CAN_MCR_SLEEP; -} - -/** - * @brief Enforces leaving the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_wakeup(CANDriver *canp) { - - canp->can->MCR &= ~CAN_MCR_SLEEP; -} -#endif /* CAN_USE_SLEEP_MODE */ - -/** - * @brief Programs the filters. - * @note This is an STM32-specific API. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] can2sb number of the first filter assigned to CAN2 - * @param[in] num number of entries in the filters array, if zero then - * a default filter is programmed - * @param[in] cfp pointer to the filters array, can be @p NULL if - * (num == 0) - * - * @api - */ -void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb, - uint32_t num, const CANFilter *cfp) { - -#if STM32_CAN_USE_CAN2 - osalDbgCheck((can2sb <= STM32_CAN_MAX_FILTERS) && - (num <= STM32_CAN_MAX_FILTERS)); -#endif - -#if STM32_CAN_USE_CAN1 - osalDbgAssert(CAND1.state == CAN_STOP, "invalid state"); -#endif -#if STM32_CAN_USE_CAN2 - osalDbgAssert(CAND2.state == CAN_STOP, "invalid state"); -#endif -#if STM32_CAN_USE_CAN3 - osalDbgAssert(CAND3.state == CAN_STOP, "invalid state"); -#endif - -#if STM32_CAN_USE_CAN1 - if (canp == &CAND1) { - can_lld_set_filters(canp, can2sb, num, cfp); - } -#endif -#if STM32_CAN_USE_CAN3 - if (canp == &CAND3) { - can_lld_set_filters(canp, can2sb, num, cfp); - } -#endif -} - -#endif /* HAL_USE_CAN */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file CANv1/hal_can_lld.c + * @brief STM32 CAN subsystem low level driver source. + * + * @addtogroup CAN + * @{ + */ + +#include "hal.h" + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* + * Addressing differences in the headers, they seem unable to agree on names. + */ +#if STM32_CAN_USE_CAN1 +#if !defined(CAN1) +#define CAN1 CAN +#endif +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief CAN1 driver identifier.*/ +#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) +CANDriver CAND1; +#endif + +/** @brief CAN2 driver identifier.*/ +#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) +CANDriver CAND2; +#endif + +/** @brief CAN3 driver identifier.*/ +#if STM32_CAN_USE_CAN3 || defined(__DOXYGEN__) +CANDriver CAND3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ +/** + * @brief Programs the filters of CAN 1 and CAN 2. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] can2sb number of the first filter assigned to CAN2 + * @param[in] num number of entries in the filters array, if zero then + * a default filter is programmed + * @param[in] cfp pointer to the filters array, can be @p NULL if + * (num == 0) + * + * @notapi + */ +static void can_lld_set_filters(CANDriver* canp, + uint32_t can2sb, + uint32_t num, + const CANFilter *cfp) { + +#if STM32_CAN_USE_CAN2 + if (canp == &CAND2) { + /* Set handle to CAN1, because CAN1 manages the filters of CAN2.*/ + canp = &CAND1; + } +#endif + + /* Temporarily enabling CAN clock.*/ +#if STM32_CAN_USE_CAN1 + if (canp == &CAND1) { + rccEnableCAN1(true); + /* Filters initialization.*/ + canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | CAN_FMR_FINIT; + canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | (can2sb << 8) | CAN_FMR_FINIT; + } +#endif + +#if STM32_CAN_USE_CAN3 + if (canp == &CAND3) { + rccEnableCAN3(true); + /* Filters initialization.*/ + canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | CAN_FMR_FINIT; + } +#endif + + if (num > 0) { + uint32_t i, fmask; + + /* All filters cleared.*/ + canp->can->FA1R = 0; + canp->can->FM1R = 0; + canp->can->FS1R = 0; + canp->can->FFA1R = 0; + +#if STM32_CAN_USE_CAN1 + if (canp == &CAND1) { + for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) { + canp->can->sFilterRegister[i].FR1 = 0; + canp->can->sFilterRegister[i].FR2 = 0; + } + } +#endif + +#if STM32_CAN_USE_CAN3 + if (canp == &CAND3) { + for (i = 0; i < STM32_CAN3_MAX_FILTERS; i++) { + canp->can->sFilterRegister[i].FR1 = 0; + canp->can->sFilterRegister[i].FR2 = 0; + } + } +#endif + + /* Scanning the filters array.*/ + for (i = 0; i < num; i++) { + fmask = 1 << cfp->filter; + if (cfp->mode) + canp->can->FM1R |= fmask; + if (cfp->scale) + canp->can->FS1R |= fmask; + if (cfp->assignment) + canp->can->FFA1R |= fmask; + canp->can->sFilterRegister[cfp->filter].FR1 = cfp->register1; + canp->can->sFilterRegister[cfp->filter].FR2 = cfp->register2; + canp->can->FA1R |= fmask; + cfp++; + } + } + else { + /* Setting up a single default filter that enables everything for both + CANs.*/ + canp->can->sFilterRegister[0].FR1 = 0; + canp->can->sFilterRegister[0].FR2 = 0; +#if STM32_CAN_USE_CAN2 + if (canp == &CAND1) { + canp->can->sFilterRegister[can2sb].FR1 = 0; + canp->can->sFilterRegister[can2sb].FR2 = 0; + } +#endif + canp->can->FM1R = 0; + canp->can->FFA1R = 0; + canp->can->FS1R = 1; + canp->can->FA1R = 1; +#if STM32_CAN_USE_CAN2 + if (canp == &CAND1) { + canp->can->FS1R |= 1 << can2sb; + canp->can->FA1R |= 1 << can2sb; + } +#endif + } + canp->can->FMR &= ~CAN_FMR_FINIT; + + /* Clock disabled, it will be enabled again in can_lld_start().*/ + /* Temporarily enabling CAN clock.*/ +#if STM32_CAN_USE_CAN1 + if (canp == &CAND1) { + rccDisableCAN1(); + } +#endif +#if STM32_CAN_USE_CAN3 + if (canp == &CAND3) { + rccDisableCAN3(); + } +#endif +} + +/** + * @brief Common TX ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_tx_handler(CANDriver *canp) { + uint32_t tsr; + eventflags_t flags; + + /* Clearing IRQ sources.*/ + tsr = canp->can->TSR; + canp->can->TSR = tsr; + + /* Flags to be signaled through the TX event source.*/ + flags = 0U; + + /* Checking mailbox 0.*/ + if ((tsr & CAN_TSR_RQCP0) != 0U) { + if ((tsr & (CAN_TSR_ALST0 | CAN_TSR_TERR0)) != 0U) { + flags |= CAN_MAILBOX_TO_MASK(1U) << 16U; + } + else { + flags |= CAN_MAILBOX_TO_MASK(1U); + } + } + + /* Checking mailbox 1.*/ + if ((tsr & CAN_TSR_RQCP1) != 0U) { + if ((tsr & (CAN_TSR_ALST1 | CAN_TSR_TERR1)) != 0U) { + flags |= CAN_MAILBOX_TO_MASK(2U) << 16U; + } + else { + flags |= CAN_MAILBOX_TO_MASK(2U); + } + } + + /* Checking mailbox 2.*/ + if ((tsr & CAN_TSR_RQCP2) != 0U) { + if ((tsr & (CAN_TSR_ALST2 | CAN_TSR_TERR2)) != 0U) { + flags |= CAN_MAILBOX_TO_MASK(3U) << 16U; + } + else { + flags |= CAN_MAILBOX_TO_MASK(3U); + } + } + + /* Signaling flags and waking up threads waiting for a transmission slot.*/ + _can_tx_empty_isr(canp, flags); +} + +/** + * @brief Common RX0 ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_rx0_handler(CANDriver *canp) { + uint32_t rf0r; + + rf0r = canp->can->RF0R; + if ((rf0r & CAN_RF0R_FMP0) > 0) { + /* No more receive events until the queue 0 has been emptied.*/ + canp->can->IER &= ~CAN_IER_FMPIE0; + _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(1U)); + } + if ((rf0r & CAN_RF0R_FOVR0) > 0) { + /* Overflow events handling.*/ + canp->can->RF0R = CAN_RF0R_FOVR0; + _can_error_isr(canp, CAN_OVERFLOW_ERROR); + } +} + +/** + * @brief Common RX1 ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_rx1_handler(CANDriver *canp) { + uint32_t rf1r; + + rf1r = canp->can->RF1R; + if ((rf1r & CAN_RF1R_FMP1) > 0) { + /* No more receive events until the queue 0 has been emptied.*/ + canp->can->IER &= ~CAN_IER_FMPIE1; + _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(2U)); + } + if ((rf1r & CAN_RF1R_FOVR1) > 0) { + /* Overflow events handling.*/ + canp->can->RF1R = CAN_RF1R_FOVR1; + _can_error_isr(canp, CAN_OVERFLOW_ERROR); + } +} + +/** + * @brief Common SCE ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_sce_handler(CANDriver *canp) { + uint32_t msr; + + /* Clearing IRQ sources.*/ + msr = canp->can->MSR; + canp->can->MSR = msr; + + /* Wakeup event.*/ +#if CAN_USE_SLEEP_MODE + if (msr & CAN_MSR_WKUI) { + canp->state = CAN_READY; + canp->can->MCR &= ~CAN_MCR_SLEEP; + _can_wakeup_isr(canp); + } +#endif /* CAN_USE_SLEEP_MODE */ + /* Error event.*/ + if (msr & CAN_MSR_ERRI) { + eventflags_t flags; + uint32_t esr = canp->can->ESR; + +#if STM32_CAN_REPORT_ALL_ERRORS + flags = (eventflags_t)(esr & 7); + if ((esr & CAN_ESR_LEC) > 0) + flags |= CAN_FRAMING_ERROR; +#else + flags = 0; +#endif + + /* The content of the ESR register is copied unchanged in the upper + half word of the listener flags mask.*/ + _can_error_isr(canp, flags | (eventflags_t)(esr << 16U)); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) +#if defined(STM32_CAN1_UNIFIED_HANDLER) +/** + * @brief CAN1 unified interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_UNIFIED_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND1); + can_lld_rx0_handler(&CAND1); + can_lld_rx1_handler(&CAND1); + can_lld_sce_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} +#else /* !defined(STM32_CAN1_UNIFIED_HANDLER) */ + +#if !defined(STM32_CAN1_TX_HANDLER) +#error "STM32_CAN1_TX_HANDLER not defined" +#endif +#if !defined(STM32_CAN1_RX0_HANDLER) +#error "STM32_CAN1_RX0_HANDLER not defined" +#endif +#if !defined(STM32_CAN1_RX1_HANDLER) +#error "STM32_CAN1_RX1_HANDLER not defined" +#endif +#if !defined(STM32_CAN1_SCE_HANDLER) +#error "STM32_CAN1_SCE_HANDLER not defined" +#endif + +/** + * @brief CAN1 TX interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 RX0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx0_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 RX1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx1_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 SCE interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_sce_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_CAN1_UNIFIED_HANDLER) */ +#endif /* STM32_CAN_USE_CAN1 */ + +#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) +#if defined(STM32_CAN2_UNIFIED_HANDLER) +/** + * @brief CAN1 unified interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_UNIFIED_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND2); + can_lld_rx0_handler(&CAND2); + can_lld_rx1_handler(&CAND2); + can_lld_sce_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} +#else /* !defined(STM32_CAN2_UNIFIED_HANDLER) */ + +#if !defined(STM32_CAN1_TX_HANDLER) +#error "STM32_CAN1_TX_HANDLER not defined" +#endif +#if !defined(STM32_CAN1_RX0_HANDLER) +#error "STM32_CAN1_RX0_HANDLER not defined" +#endif +#if !defined(STM32_CAN1_RX1_HANDLER) +#error "STM32_CAN1_RX1_HANDLER not defined" +#endif +#if !defined(STM32_CAN1_SCE_HANDLER) +#error "STM32_CAN1_SCE_HANDLER not defined" +#endif + +/** + * @brief CAN2 TX interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_TX_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN2 RX0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_RX0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx0_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN2 RX1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_RX1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx1_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN2 SCE interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_SCE_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_sce_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_CAN2_UNIFIED_HANDLER) */ +#endif /* STM32_CAN_USE_CAN2 */ + +#if STM32_CAN_USE_CAN3 || defined(__DOXYGEN__) +#if defined(STM32_CAN3_UNIFIED_HANDLER) +/** + * @brief CAN1 unified interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN3_UNIFIED_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND3); + can_lld_rx0_handler(&CAND3); + can_lld_rx1_handler(&CAND3); + can_lld_sce_handler(&CAND3); + + OSAL_IRQ_EPILOGUE(); +} +#else /* !defined(STM32_CAN3_UNIFIED_HANDLER) */ + +#if !defined(STM32_CAN3_TX_HANDLER) +#error "STM32_CAN3_TX_HANDLER not defined" +#endif +#if !defined(STM32_CAN3_RX0_HANDLER) +#error "STM32_CAN3_RX0_HANDLER not defined" +#endif +#if !defined(STM32_CAN3_RX1_HANDLER) +#error "STM32_CAN3_RX1_HANDLER not defined" +#endif +#if !defined(STM32_CAN3_SCE_HANDLER) +#error "STM32_CAN3_SCE_HANDLER not defined" +#endif + +/** + * @brief CAN3 TX interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN3_TX_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN3 RX0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN3_RX0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx0_handler(&CAND3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 RX3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN3_RX1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx1_handler(&CAND3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 SCE interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN3_SCE_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_sce_handler(&CAND3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_CAN1_UNIFIED_HANDLER) */ +#endif /* STM32_CAN_USE_CAN1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level CAN driver initialization. + * + * @notapi + */ +void can_lld_init(void) { + +#if STM32_CAN_USE_CAN1 + /* Driver initialization.*/ + canObjectInit(&CAND1); + CAND1.can = CAN1; +#if defined(STM32_CAN1_UNIFIED_NUMBER) + nvicEnableVector(STM32_CAN1_UNIFIED_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); +#else + nvicEnableVector(STM32_CAN1_TX_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN1_RX0_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN1_RX1_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN1_SCE_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); +#endif +#endif + +#if STM32_CAN_USE_CAN2 + /* Driver initialization.*/ + canObjectInit(&CAND2); + CAND2.can = CAN2; +#if defined(STM32_CAN2_UNIFIED_NUMBER) + nvicEnableVector(STM32_CAN2_UNIFIED_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); +#else + nvicEnableVector(STM32_CAN2_TX_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN2_RX0_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN2_RX1_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN2_SCE_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); +#endif +#endif + +#if STM32_CAN_USE_CAN3 + /* Driver initialization.*/ + canObjectInit(&CAND3); + CAND3.can = CAN3; +#if defined(STM32_CAN3_UNIFIED_NUMBER) + nvicEnableVector(STM32_CAN3_UNIFIED_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); +#else + nvicEnableVector(STM32_CAN3_TX_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN3_RX0_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN3_RX1_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN3_SCE_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY); +#endif +#endif + + /* Filters initialization.*/ +#if STM32_CAN_USE_CAN1 +#if STM32_HAS_CAN2 + can_lld_set_filters(&CAND1, STM32_CAN_MAX_FILTERS / 2, 0, NULL); +#else + can_lld_set_filters(&CAND1, STM32_CAN_MAX_FILTERS, 0, NULL); +#endif +#endif + +#if STM32_HAS_CAN3 +#if STM32_CAN_USE_CAN3 + can_lld_set_filters(&CAND3, STM32_CAN3_MAX_FILTERS, 0, NULL); +#endif +#endif +} + +/** + * @brief Configures and activates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_start(CANDriver *canp) { + + /* Clock activation.*/ +#if STM32_CAN_USE_CAN1 + if (&CAND1 == canp) { + rccEnableCAN1(true); + } +#endif + +#if STM32_CAN_USE_CAN2 + if (&CAND2 == canp) { + rccEnableCAN1(true); /* CAN 2 requires CAN1, so enabling it first.*/ + rccEnableCAN2(true); + } +#endif + +#if STM32_CAN_USE_CAN3 + if (&CAND3 == canp) { + rccEnableCAN3(true); + } +#endif + + /* Configuring CAN. */ + canp->can->MCR = CAN_MCR_INRQ; + while ((canp->can->MSR & CAN_MSR_INAK) == 0) + osalThreadSleepS(1); + canp->can->BTR = canp->config->btr; + canp->can->MCR = canp->config->mcr; + + /* Interrupt sources initialization.*/ +#if STM32_CAN_REPORT_ALL_ERRORS + canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 | + CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE | + CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | + CAN_IER_FOVIE0 | CAN_IER_FOVIE1; +#else + canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 | + CAN_IER_WKUIE | CAN_IER_ERRIE | + CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | + CAN_IER_FOVIE0 | CAN_IER_FOVIE1; +#endif +} + +/** + * @brief Deactivates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_stop(CANDriver *canp) { + + /* If in ready state then disables the CAN peripheral.*/ + if (canp->state == CAN_READY) { +#if STM32_CAN_USE_CAN1 + if (&CAND1 == canp) { + CAN1->MCR = 0x00010002; /* Register reset value. */ + CAN1->IER = 0x00000000; /* All sources disabled. */ +#if STM32_CAN_USE_CAN2 + /* If CAND2 is stopped then CAN1 clock is stopped here.*/ + if (CAND2.state == CAN_STOP) +#endif + { + rccDisableCAN1(); + } + } +#endif + +#if STM32_CAN_USE_CAN2 + if (&CAND2 == canp) { + CAN2->MCR = 0x00010002; /* Register reset value. */ + CAN2->IER = 0x00000000; /* All sources disabled. */ +#if STM32_CAN_USE_CAN1 + /* If CAND1 is stopped then CAN1 clock is stopped here.*/ + if (CAND1.state == CAN_STOP) +#endif + { + rccDisableCAN1(); + } + rccDisableCAN2(); + } +#endif + +#if STM32_CAN_USE_CAN3 + if (&CAND3 == canp) { + CAN3->MCR = 0x00010002; /* Register reset value. */ + CAN3->IER = 0x00000000; /* All sources disabled. */ + rccDisableCAN3(); + } +#endif + } +} + +/** + * @brief Determines whether a frame can be transmitted. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @return The queue space availability. + * @retval false no space in the transmit queue. + * @retval true transmit slot available. + * + * @notapi + */ +bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { + + switch (mailbox) { + case CAN_ANY_MAILBOX: + return (canp->can->TSR & CAN_TSR_TME) != 0; + case 1: + return (canp->can->TSR & CAN_TSR_TME0) != 0; + case 2: + return (canp->can->TSR & CAN_TSR_TME1) != 0; + case 3: + return (canp->can->TSR & CAN_TSR_TME2) != 0; + default: + return false; + } +} + +/** + * @brief Inserts a frame into the transmit queue. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] ctfp pointer to the CAN frame to be transmitted + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @notapi + */ +void can_lld_transmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp) { + uint32_t tir; + CAN_TxMailBox_TypeDef *tmbp; + + /* Pointer to a free transmission mailbox.*/ + switch (mailbox) { + case CAN_ANY_MAILBOX: + if ((DBGMCU->IDCODE >> 16) == 0x1001) { + /* real STM32 */ + tmbp = &canp->can->sTxMailBox[(canp->can->TSR & CAN_TSR_CODE) >> 24]; + } else { + int n; + /* GD32 */ + if ((canp->can->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) + n = 0; + else if ((canp->can->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) + n = 1; + else if ((canp->can->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) + n = 2; + else { + /* silence? */ + return; + } + tmbp = &canp->can->sTxMailBox[n]; + } + break; + case 1: + tmbp = &canp->can->sTxMailBox[0]; + break; + case 2: + tmbp = &canp->can->sTxMailBox[1]; + break; + case 3: + tmbp = &canp->can->sTxMailBox[2]; + break; + default: + return; + } + + /* Preparing the message.*/ + if (ctfp->IDE) + tir = ((uint32_t)ctfp->EID << 3) | ((uint32_t)ctfp->RTR << 1) | + CAN_TI0R_IDE; + else + tir = ((uint32_t)ctfp->SID << 21) | ((uint32_t)ctfp->RTR << 1); + tmbp->TDTR = ctfp->DLC; + tmbp->TDLR = ctfp->data32[0]; + tmbp->TDHR = ctfp->data32[1]; + tmbp->TIR = tir | CAN_TI0R_TXRQ; +} + +/** + * @brief Determines whether a frame has been received. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @return The queue space availability. + * @retval false no space in the transmit queue. + * @retval true transmit slot available. + * + * @notapi + */ +bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { + + switch (mailbox) { + case CAN_ANY_MAILBOX: + return ((canp->can->RF0R & CAN_RF0R_FMP0) != 0 || + (canp->can->RF1R & CAN_RF1R_FMP1) != 0); + case 1: + return (canp->can->RF0R & CAN_RF0R_FMP0) != 0; + case 2: + return (canp->can->RF1R & CAN_RF1R_FMP1) != 0; + default: + return false; + } +} + +/** + * @brief Receives a frame from the input queue. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[out] crfp pointer to the buffer where the CAN frame is copied + * + * @notapi + */ +void can_lld_receive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp) { + uint32_t rir, rdtr; + + if (mailbox == CAN_ANY_MAILBOX) { + if ((canp->can->RF0R & CAN_RF0R_FMP0) != 0) + mailbox = 1; + else if ((canp->can->RF1R & CAN_RF1R_FMP1) != 0) + mailbox = 2; + else { + /* Should not happen, do nothing.*/ + return; + } + } + switch (mailbox) { + case 1: + /* Fetches the message.*/ + rir = canp->can->sFIFOMailBox[0].RIR; + rdtr = canp->can->sFIFOMailBox[0].RDTR; + crfp->data32[0] = canp->can->sFIFOMailBox[0].RDLR; + crfp->data32[1] = canp->can->sFIFOMailBox[0].RDHR; + + /* Releases the mailbox.*/ + canp->can->RF0R = CAN_RF0R_RFOM0; + + /* If the queue is empty re-enables the interrupt in order to generate + events again.*/ + if ((canp->can->RF0R & CAN_RF0R_FMP0) == 0) + canp->can->IER |= CAN_IER_FMPIE0; + break; + case 2: + /* Fetches the message.*/ + rir = canp->can->sFIFOMailBox[1].RIR; + rdtr = canp->can->sFIFOMailBox[1].RDTR; + crfp->data32[0] = canp->can->sFIFOMailBox[1].RDLR; + crfp->data32[1] = canp->can->sFIFOMailBox[1].RDHR; + + /* Releases the mailbox.*/ + canp->can->RF1R = CAN_RF1R_RFOM1; + + /* If the queue is empty re-enables the interrupt in order to generate + events again.*/ + if ((canp->can->RF1R & CAN_RF1R_FMP1) == 0) + canp->can->IER |= CAN_IER_FMPIE1; + break; + default: + /* Should not happen, do nothing.*/ + return; + } + + /* Decodes the various fields in the RX frame.*/ + crfp->RTR = (rir & CAN_RI0R_RTR) >> 1; + crfp->IDE = (rir & CAN_RI0R_IDE) >> 2; + if (crfp->IDE) + crfp->EID = rir >> 3; + else + crfp->SID = rir >> 21; + crfp->DLC = rdtr & CAN_RDT0R_DLC; + crfp->FMI = (uint8_t)(rdtr >> 8); + crfp->TIME = (uint16_t)(rdtr >> 16); +} + +/** + * @brief Tries to abort an ongoing transmission. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number + * + * @notapi + */ +void can_lld_abort(CANDriver *canp, + canmbx_t mailbox) { + + canp->can->TSR = 128U << ((mailbox - 1U) * 8U); +} + +#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) +/** + * @brief Enters the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_sleep(CANDriver *canp) { + + canp->can->MCR |= CAN_MCR_SLEEP; +} + +/** + * @brief Enforces leaving the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_wakeup(CANDriver *canp) { + + canp->can->MCR &= ~CAN_MCR_SLEEP; +} +#endif /* CAN_USE_SLEEP_MODE */ + +/** + * @brief Programs the filters. + * @note This is an STM32-specific API. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] can2sb number of the first filter assigned to CAN2 + * @param[in] num number of entries in the filters array, if zero then + * a default filter is programmed + * @param[in] cfp pointer to the filters array, can be @p NULL if + * (num == 0) + * + * @api + */ +void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb, + uint32_t num, const CANFilter *cfp) { + +#if STM32_CAN_USE_CAN2 + osalDbgCheck((can2sb <= STM32_CAN_MAX_FILTERS) && + (num <= STM32_CAN_MAX_FILTERS)); +#endif + +#if STM32_CAN_USE_CAN1 + osalDbgAssert(CAND1.state == CAN_STOP, "invalid state"); +#endif +#if STM32_CAN_USE_CAN2 + osalDbgAssert(CAND2.state == CAN_STOP, "invalid state"); +#endif +#if STM32_CAN_USE_CAN3 + osalDbgAssert(CAND3.state == CAN_STOP, "invalid state"); +#endif + +#if STM32_CAN_USE_CAN1 + if (canp == &CAND1) { + can_lld_set_filters(canp, can2sb, num, cfp); + } +#endif +#if STM32_CAN_USE_CAN3 + if (canp == &CAND3) { + can_lld_set_filters(canp, can2sb, num, cfp); + } +#endif +} + +#endif /* HAL_USE_CAN */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h b/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h index e4eb6f6d2c..3235a228e7 100644 --- a/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h +++ b/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h @@ -1,471 +1,471 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file CANv1/hal_can_lld.h - * @brief STM32 CAN subsystem low level driver header. - * - * @addtogroup CAN - * @{ - */ - -#ifndef HAL_CAN_LLD_H -#define HAL_CAN_LLD_H - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* - * The following macros from the ST header file are replaced with better - * equivalents. - */ -#undef CAN_BTR_BRP -#undef CAN_BTR_TS1 -#undef CAN_BTR_TS2 -#undef CAN_BTR_SJW - -/** - * @brief This switch defines whether the driver implementation supports - * a low power switch mode with automatic an wakeup feature. - */ -#define CAN_SUPPORTS_SLEEP TRUE - -/** - * @brief This implementation supports three transmit mailboxes. - */ -#define CAN_TX_MAILBOXES 3 - -/** - * @brief This implementation supports two receive mailboxes. - */ -#define CAN_RX_MAILBOXES 2 - -/** - * @name CAN registers helper macros - * @{ - */ -#define CAN_BTR_BRP(n) (n) /**< @brief BRP field macro.*/ -#define CAN_BTR_TS1(n) ((n) << 16) /**< @brief TS1 field macro.*/ -#define CAN_BTR_TS2(n) ((n) << 20) /**< @brief TS2 field macro.*/ -#define CAN_BTR_SJW(n) ((n) << 24) /**< @brief SJW field macro.*/ - -#define CAN_IDE_STD 0 /**< @brief Standard id. */ -#define CAN_IDE_EXT 1 /**< @brief Extended id. */ - -#define CAN_RTR_DATA 0 /**< @brief Data frame. */ -#define CAN_RTR_REMOTE 1 /**< @brief Remote frame. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief CAN pedantic errors report. - * @details Use of this option is IRQ-intensive. - */ -#if !defined(STM32_CAN_REPORT_ALL_ERRORS) || defined(__DOXYGEN__) -#define STM32_CAN_REPORT_ALL_ERRORS FALSE -#endif - -/** - * @brief CAN1 driver enable switch. - * @details If set to @p TRUE the support for CAN1 is included. - */ -#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__) -#define STM32_CAN_USE_CAN1 FALSE -#endif - -/** - * @brief CAN2 driver enable switch. - * @details If set to @p TRUE the support for CAN2 is included. - */ -#if !defined(STM32_CAN_USE_CAN2) || defined(__DOXYGEN__) -#define STM32_CAN_USE_CAN2 FALSE -#endif - -/** - * @brief CAN3 driver enable switch. - * @details If set to @p TRUE the support for CAN3 is included. - */ -#if !defined(STM32_CAN_USE_CAN3) || defined(__DOXYGEN__) -#define STM32_CAN_USE_CAN3 FALSE -#endif - -/** - * @brief CAN1 interrupt priority level setting. - */ -#if !defined(STM32_CAN_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 -#endif -/** @} */ - -/** - * @brief CAN2 interrupt priority level setting. - */ -#if !defined(STM32_CAN_CAN2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CAN_CAN2_IRQ_PRIORITY 11 -#endif -/** @} */ - -/** - * @brief CAN3 interrupt priority level setting. - */ -#if !defined(STM32_CAN_CAN3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CAN_CAN3_IRQ_PRIORITY 11 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_CAN1) -#error "STM32_HAS_CAN1 not defined in registry" -#endif - -#if !defined(STM32_HAS_CAN2) -#error "STM32_HAS_CAN2 not defined in registry" -#endif - -#if !defined(STM32_HAS_CAN3) -#error "STM32_HAS_CAN3 not defined in registry" -#endif - -#if (STM32_HAS_CAN1 | STM32_HAS_CAN2) && !defined(STM32_CAN_MAX_FILTERS) -#error "STM32_CAN_MAX_FILTERS not defined in registry" -#endif - -#if STM32_HAS_CAN3 && !defined(STM32_CAN3_MAX_FILTERS) -#error "STM32_CAN3_MAX_FILTERS not defined in registry" -#endif - -#if STM32_CAN_USE_CAN1 && !STM32_HAS_CAN1 -#error "CAN1 not present in the selected device" -#endif - -#if STM32_CAN_USE_CAN2 && !STM32_HAS_CAN2 -#error "CAN2 not present in the selected device" -#endif - -#if STM32_CAN_USE_CAN3 && !STM32_HAS_CAN3 -#error "CAN2 not present in the selected device" -#endif - -#if !STM32_CAN_USE_CAN1 && !STM32_CAN_USE_CAN2 && !STM32_CAN_USE_CAN3 -#error "CAN driver activated but no CAN peripheral assigned" -#endif - -#if !STM32_CAN_USE_CAN1 && STM32_CAN_USE_CAN2 -#error "CAN2 requires CAN1, it cannot operate independently" -#endif - -#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP -#error "CAN sleep mode not supported in this architecture" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an CAN driver. - */ -typedef struct CANDriver CANDriver; - -/** - * @brief Type of a transmission mailbox index. - */ -typedef uint32_t canmbx_t; - -#if (CAN_ENFORCE_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a CAN notification callback. - * - * @param[in] canp pointer to the @p CANDriver object triggering the - * callback - * @param[in] flags flags associated to the mailbox callback - */ -typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags); -#endif - -/** - * @brief CAN transmission frame. - * @note Accessing the frame data as word16 or word32 is not portable because - * machine data endianness, it can be still useful for a quick filling. - */ -typedef struct { - struct { - uint8_t DLC:4; /**< @brief Data length. */ - uint8_t RTR:1; /**< @brief Frame type. */ - uint8_t IDE:1; /**< @brief Identifier type. */ - }; - union { - struct { - uint32_t SID:11; /**< @brief Standard identifier.*/ - }; - struct { - uint32_t EID:29; /**< @brief Extended identifier.*/ - }; - }; - union { - uint8_t data8[8]; /**< @brief Frame data. */ - uint16_t data16[4]; /**< @brief Frame data. */ - uint32_t data32[2]; /**< @brief Frame data. */ - uint64_t data64[1]; /**< @brief Frame data. */ - }; -} CANTxFrame; - -/** - * @brief CAN received frame. - * @note Accessing the frame data as word16 or word32 is not portable because - * machine data endianness, it can be still useful for a quick filling. - */ -typedef struct { - struct { - uint8_t FMI; /**< @brief Filter id. */ - uint16_t TIME; /**< @brief Time stamp. */ - }; - struct { - uint8_t DLC:4; /**< @brief Data length. */ - uint8_t RTR:1; /**< @brief Frame type. */ - uint8_t IDE:1; /**< @brief Identifier type. */ - }; - union { - struct { - uint32_t SID:11; /**< @brief Standard identifier.*/ - }; - struct { - uint32_t EID:29; /**< @brief Extended identifier.*/ - }; - }; - union { - uint8_t data8[8]; /**< @brief Frame data. */ - uint16_t data16[4]; /**< @brief Frame data. */ - uint32_t data32[2]; /**< @brief Frame data. */ - uint64_t data64[1]; /**< @brief Frame data. */ - }; -} CANRxFrame; - -/** - * @brief CAN filter. - * @note Refer to the STM32 reference manual for info about filters. - */ -typedef struct { - /** - * @brief Number of the filter bank to be programmed. - */ - uint32_t filter:16; - /** - * @brief Filter mode. - * @note This bit represent the CAN_FM1R register bit associated to this - * filter (0=mask mode, 1=list mode). - */ - uint32_t mode:1; - /** - * @brief Filter scale. - * @note This bit represent the CAN_FS1R register bit associated to this - * filter (0=16 bits mode, 1=32 bits mode). - */ - uint32_t scale:1; - /** - * @brief Filter mode. - * @note This bit represent the CAN_FFA1R register bit associated to this - * filter, must be set to zero in this version of the driver. - */ - uint32_t assignment:1; - /** - * @brief Filter register 1 (identifier). - */ - uint32_t register1; - /** - * @brief Filter register 2 (mask/identifier depending on mode=0/1). - */ - uint32_t register2; -} CANFilter; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief CAN MCR register initialization data. - * @note Some bits in this register are enforced by the driver regardless - * their status in this field. - */ - uint32_t mcr; - /** - * @brief CAN BTR register initialization data. - * @note Some bits in this register are enforced by the driver regardless - * their status in this field. - */ - uint32_t btr; -} CANConfig; - -/** - * @brief Structure representing an CAN driver. - */ -struct CANDriver { - /** - * @brief Driver state. - */ - canstate_t state; - /** - * @brief Current configuration data. - */ - const CANConfig *config; - /** - * @brief Transmission threads queue. - */ - threads_queue_t txqueue; - /** - * @brief Receive threads queue. - */ - threads_queue_t rxqueue; -#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__) - /** - * @brief One or more frames become available. - * @note After broadcasting this event it will not be broadcasted again - * until the received frames queue has been completely emptied. It - * is not broadcasted for each received frame. It is - * responsibility of the application to empty the queue by - * repeatedly invoking @p canReceive() when listening to this event. - * This behavior minimizes the interrupt served by the system - * because CAN traffic. - * @note The flags associated to the listeners will indicate which - * receive mailboxes become non-empty. - */ - event_source_t rxfull_event; - /** - * @brief One or more transmission mailbox become available. - * @note The flags associated to the listeners will indicate which - * transmit mailboxes become empty. - * @note The upper 16 bits are transmission error flags associated - * to the transmit mailboxes. - */ - event_source_t txempty_event; - /** - * @brief A CAN bus error happened. - * @note The flags associated to the listeners will indicate that - * receive error(s) have occurred. - * @note In this implementation the upper 16 bits are filled with the - * unprocessed content of the ESR register. - */ - event_source_t error_event; -#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) - /** - * @brief Entering sleep state event. - */ - event_source_t sleep_event; - /** - * @brief Exiting sleep state event. - */ - event_source_t wakeup_event; -#endif /* CAN_USE_SLEEP_MODE */ -#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */ - /** - * @brief One or more frames become available. - * @note After calling this function it will not be called again - * until the received frames queue has been completely emptied. It - * is not called for each received frame. It is - * responsibility of the application to empty the queue by - * repeatedly invoking @p chTryReceiveI(). - * This behavior minimizes the interrupt served by the system - * because CAN traffic. - */ - can_callback_t rxfull_cb; - /** - * @brief One or more transmission mailbox become available. - * @note The flags associated to the callback will indicate which - * transmit mailboxes become empty. - */ - can_callback_t txempty_cb; - /** - * @brief A CAN bus error happened. - */ - can_callback_t error_cb; -#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__) - /** - * @brief Exiting sleep state. - */ - can_callback_t wakeup_cb; -#endif -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the CAN registers. - */ - CAN_TypeDef *can; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_CAN_USE_CAN1 && !defined(__DOXYGEN__) -extern CANDriver CAND1; -#endif - -#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__) -extern CANDriver CAND2; -#endif - -#if STM32_CAN_USE_CAN3 && !defined(__DOXYGEN__) -extern CANDriver CAND3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void can_lld_init(void); - void can_lld_start(CANDriver *canp); - void can_lld_stop(CANDriver *canp); - bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox); - void can_lld_transmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *crfp); - bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox); - void can_lld_receive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *ctfp); - void can_lld_abort(CANDriver *canp, - canmbx_t mailbox); -#if CAN_USE_SLEEP_MODE - void can_lld_sleep(CANDriver *canp); - void can_lld_wakeup(CANDriver *canp); -#endif /* CAN_USE_SLEEP_MODE */ - void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb, - uint32_t num, const CANFilter *cfp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_CAN */ - -#endif /* HAL_CAN_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file CANv1/hal_can_lld.h + * @brief STM32 CAN subsystem low level driver header. + * + * @addtogroup CAN + * @{ + */ + +#ifndef HAL_CAN_LLD_H +#define HAL_CAN_LLD_H + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * The following macros from the ST header file are replaced with better + * equivalents. + */ +#undef CAN_BTR_BRP +#undef CAN_BTR_TS1 +#undef CAN_BTR_TS2 +#undef CAN_BTR_SJW + +/** + * @brief This switch defines whether the driver implementation supports + * a low power switch mode with automatic an wakeup feature. + */ +#define CAN_SUPPORTS_SLEEP TRUE + +/** + * @brief This implementation supports three transmit mailboxes. + */ +#define CAN_TX_MAILBOXES 3 + +/** + * @brief This implementation supports two receive mailboxes. + */ +#define CAN_RX_MAILBOXES 2 + +/** + * @name CAN registers helper macros + * @{ + */ +#define CAN_BTR_BRP(n) (n) /**< @brief BRP field macro.*/ +#define CAN_BTR_TS1(n) ((n) << 16) /**< @brief TS1 field macro.*/ +#define CAN_BTR_TS2(n) ((n) << 20) /**< @brief TS2 field macro.*/ +#define CAN_BTR_SJW(n) ((n) << 24) /**< @brief SJW field macro.*/ + +#define CAN_IDE_STD 0 /**< @brief Standard id. */ +#define CAN_IDE_EXT 1 /**< @brief Extended id. */ + +#define CAN_RTR_DATA 0 /**< @brief Data frame. */ +#define CAN_RTR_REMOTE 1 /**< @brief Remote frame. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief CAN pedantic errors report. + * @details Use of this option is IRQ-intensive. + */ +#if !defined(STM32_CAN_REPORT_ALL_ERRORS) || defined(__DOXYGEN__) +#define STM32_CAN_REPORT_ALL_ERRORS FALSE +#endif + +/** + * @brief CAN1 driver enable switch. + * @details If set to @p TRUE the support for CAN1 is included. + */ +#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__) +#define STM32_CAN_USE_CAN1 FALSE +#endif + +/** + * @brief CAN2 driver enable switch. + * @details If set to @p TRUE the support for CAN2 is included. + */ +#if !defined(STM32_CAN_USE_CAN2) || defined(__DOXYGEN__) +#define STM32_CAN_USE_CAN2 FALSE +#endif + +/** + * @brief CAN3 driver enable switch. + * @details If set to @p TRUE the support for CAN3 is included. + */ +#if !defined(STM32_CAN_USE_CAN3) || defined(__DOXYGEN__) +#define STM32_CAN_USE_CAN3 FALSE +#endif + +/** + * @brief CAN1 interrupt priority level setting. + */ +#if !defined(STM32_CAN_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#endif +/** @} */ + +/** + * @brief CAN2 interrupt priority level setting. + */ +#if !defined(STM32_CAN_CAN2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 +#endif +/** @} */ + +/** + * @brief CAN3 interrupt priority level setting. + */ +#if !defined(STM32_CAN_CAN3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CAN_CAN3_IRQ_PRIORITY 11 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_CAN1) +#error "STM32_HAS_CAN1 not defined in registry" +#endif + +#if !defined(STM32_HAS_CAN2) +#error "STM32_HAS_CAN2 not defined in registry" +#endif + +#if !defined(STM32_HAS_CAN3) +#error "STM32_HAS_CAN3 not defined in registry" +#endif + +#if (STM32_HAS_CAN1 | STM32_HAS_CAN2) && !defined(STM32_CAN_MAX_FILTERS) +#error "STM32_CAN_MAX_FILTERS not defined in registry" +#endif + +#if STM32_HAS_CAN3 && !defined(STM32_CAN3_MAX_FILTERS) +#error "STM32_CAN3_MAX_FILTERS not defined in registry" +#endif + +#if STM32_CAN_USE_CAN1 && !STM32_HAS_CAN1 +#error "CAN1 not present in the selected device" +#endif + +#if STM32_CAN_USE_CAN2 && !STM32_HAS_CAN2 +#error "CAN2 not present in the selected device" +#endif + +#if STM32_CAN_USE_CAN3 && !STM32_HAS_CAN3 +#error "CAN2 not present in the selected device" +#endif + +#if !STM32_CAN_USE_CAN1 && !STM32_CAN_USE_CAN2 && !STM32_CAN_USE_CAN3 +#error "CAN driver activated but no CAN peripheral assigned" +#endif + +#if !STM32_CAN_USE_CAN1 && STM32_CAN_USE_CAN2 +#error "CAN2 requires CAN1, it cannot operate independently" +#endif + +#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP +#error "CAN sleep mode not supported in this architecture" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an CAN driver. + */ +typedef struct CANDriver CANDriver; + +/** + * @brief Type of a transmission mailbox index. + */ +typedef uint32_t canmbx_t; + +#if (CAN_ENFORCE_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a CAN notification callback. + * + * @param[in] canp pointer to the @p CANDriver object triggering the + * callback + * @param[in] flags flags associated to the mailbox callback + */ +typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags); +#endif + +/** + * @brief CAN transmission frame. + * @note Accessing the frame data as word16 or word32 is not portable because + * machine data endianness, it can be still useful for a quick filling. + */ +typedef struct { + struct { + uint8_t DLC:4; /**< @brief Data length. */ + uint8_t RTR:1; /**< @brief Frame type. */ + uint8_t IDE:1; /**< @brief Identifier type. */ + }; + union { + struct { + uint32_t SID:11; /**< @brief Standard identifier.*/ + }; + struct { + uint32_t EID:29; /**< @brief Extended identifier.*/ + }; + }; + union { + uint8_t data8[8]; /**< @brief Frame data. */ + uint16_t data16[4]; /**< @brief Frame data. */ + uint32_t data32[2]; /**< @brief Frame data. */ + uint64_t data64[1]; /**< @brief Frame data. */ + }; +} CANTxFrame; + +/** + * @brief CAN received frame. + * @note Accessing the frame data as word16 or word32 is not portable because + * machine data endianness, it can be still useful for a quick filling. + */ +typedef struct { + struct { + uint8_t FMI; /**< @brief Filter id. */ + uint16_t TIME; /**< @brief Time stamp. */ + }; + struct { + uint8_t DLC:4; /**< @brief Data length. */ + uint8_t RTR:1; /**< @brief Frame type. */ + uint8_t IDE:1; /**< @brief Identifier type. */ + }; + union { + struct { + uint32_t SID:11; /**< @brief Standard identifier.*/ + }; + struct { + uint32_t EID:29; /**< @brief Extended identifier.*/ + }; + }; + union { + uint8_t data8[8]; /**< @brief Frame data. */ + uint16_t data16[4]; /**< @brief Frame data. */ + uint32_t data32[2]; /**< @brief Frame data. */ + uint64_t data64[1]; /**< @brief Frame data. */ + }; +} CANRxFrame; + +/** + * @brief CAN filter. + * @note Refer to the STM32 reference manual for info about filters. + */ +typedef struct { + /** + * @brief Number of the filter bank to be programmed. + */ + uint32_t filter:16; + /** + * @brief Filter mode. + * @note This bit represent the CAN_FM1R register bit associated to this + * filter (0=mask mode, 1=list mode). + */ + uint32_t mode:1; + /** + * @brief Filter scale. + * @note This bit represent the CAN_FS1R register bit associated to this + * filter (0=16 bits mode, 1=32 bits mode). + */ + uint32_t scale:1; + /** + * @brief Filter mode. + * @note This bit represent the CAN_FFA1R register bit associated to this + * filter, must be set to zero in this version of the driver. + */ + uint32_t assignment:1; + /** + * @brief Filter register 1 (identifier). + */ + uint32_t register1; + /** + * @brief Filter register 2 (mask/identifier depending on mode=0/1). + */ + uint32_t register2; +} CANFilter; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief CAN MCR register initialization data. + * @note Some bits in this register are enforced by the driver regardless + * their status in this field. + */ + uint32_t mcr; + /** + * @brief CAN BTR register initialization data. + * @note Some bits in this register are enforced by the driver regardless + * their status in this field. + */ + uint32_t btr; +} CANConfig; + +/** + * @brief Structure representing an CAN driver. + */ +struct CANDriver { + /** + * @brief Driver state. + */ + canstate_t state; + /** + * @brief Current configuration data. + */ + const CANConfig *config; + /** + * @brief Transmission threads queue. + */ + threads_queue_t txqueue; + /** + * @brief Receive threads queue. + */ + threads_queue_t rxqueue; +#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__) + /** + * @brief One or more frames become available. + * @note After broadcasting this event it will not be broadcasted again + * until the received frames queue has been completely emptied. It + * is not broadcasted for each received frame. It is + * responsibility of the application to empty the queue by + * repeatedly invoking @p canReceive() when listening to this event. + * This behavior minimizes the interrupt served by the system + * because CAN traffic. + * @note The flags associated to the listeners will indicate which + * receive mailboxes become non-empty. + */ + event_source_t rxfull_event; + /** + * @brief One or more transmission mailbox become available. + * @note The flags associated to the listeners will indicate which + * transmit mailboxes become empty. + * @note The upper 16 bits are transmission error flags associated + * to the transmit mailboxes. + */ + event_source_t txempty_event; + /** + * @brief A CAN bus error happened. + * @note The flags associated to the listeners will indicate that + * receive error(s) have occurred. + * @note In this implementation the upper 16 bits are filled with the + * unprocessed content of the ESR register. + */ + event_source_t error_event; +#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) + /** + * @brief Entering sleep state event. + */ + event_source_t sleep_event; + /** + * @brief Exiting sleep state event. + */ + event_source_t wakeup_event; +#endif /* CAN_USE_SLEEP_MODE */ +#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */ + /** + * @brief One or more frames become available. + * @note After calling this function it will not be called again + * until the received frames queue has been completely emptied. It + * is not called for each received frame. It is + * responsibility of the application to empty the queue by + * repeatedly invoking @p chTryReceiveI(). + * This behavior minimizes the interrupt served by the system + * because CAN traffic. + */ + can_callback_t rxfull_cb; + /** + * @brief One or more transmission mailbox become available. + * @note The flags associated to the callback will indicate which + * transmit mailboxes become empty. + */ + can_callback_t txempty_cb; + /** + * @brief A CAN bus error happened. + */ + can_callback_t error_cb; +#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__) + /** + * @brief Exiting sleep state. + */ + can_callback_t wakeup_cb; +#endif +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the CAN registers. + */ + CAN_TypeDef *can; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_CAN_USE_CAN1 && !defined(__DOXYGEN__) +extern CANDriver CAND1; +#endif + +#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__) +extern CANDriver CAND2; +#endif + +#if STM32_CAN_USE_CAN3 && !defined(__DOXYGEN__) +extern CANDriver CAND3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void can_lld_init(void); + void can_lld_start(CANDriver *canp); + void can_lld_stop(CANDriver *canp); + bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox); + void can_lld_transmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *crfp); + bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox); + void can_lld_receive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *ctfp); + void can_lld_abort(CANDriver *canp, + canmbx_t mailbox); +#if CAN_USE_SLEEP_MODE + void can_lld_sleep(CANDriver *canp); + void can_lld_wakeup(CANDriver *canp); +#endif /* CAN_USE_SLEEP_MODE */ + void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb, + uint32_t num, const CANFilter *cfp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_CAN */ + +#endif /* HAL_CAN_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/CRYPv1/driver.mk b/os/hal/ports/STM32/LLD/CRYPv1/driver.mk index 43936d3e30..8774b92077 100644 --- a/os/hal/ports/STM32/LLD/CRYPv1/driver.mk +++ b/os/hal/ports/STM32/LLD/CRYPv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_CRY TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_CRY TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1 diff --git a/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c b/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c index 1d83e199bb..dab504d72d 100644 --- a/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c +++ b/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c @@ -1,1901 +1,1901 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file CRYPv1/hal_crypto_lld.c - * @brief STM32 cryptographic subsystem low level driver source. - * - * @addtogroup CRYPTO - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define CRYP1_IN_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_CRY_CRYP1_IN_DMA_STREAM, \ - STM32_CRYP1_IN_DMA_CHN) - -#define CRYP1_OUT_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_CRY_CRYP1_OUT_DMA_STREAM, \ - STM32_CRYP1_OUT_DMA_CHN) - -#define HASH1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_CRY_HASH1_DMA_STREAM, \ - STM32_HASH1_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief CRY1 driver identifier.*/ -#if (STM32_CRY_ENABLED1 == TRUE) || defined(__DOXYGEN__) -CRYDriver CRYD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if (STM32_CRY_USE_CRYP1 == TRUE) || defined (__DOXYGEN__) -/** - * @brief Setting AES key for encryption. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] algomode algorithm mode field of CR register - */ -static inline void cryp_set_key_encrypt(CRYDriver *cryp, uint32_t algomode) { - uint32_t cr; - - /* Loading key data.*/ - CRYP->K0LR = cryp->cryp_k[0]; - CRYP->K0RR = cryp->cryp_k[1]; - CRYP->K1LR = cryp->cryp_k[2]; - CRYP->K1RR = cryp->cryp_k[3]; - CRYP->K2LR = cryp->cryp_k[4]; - CRYP->K2RR = cryp->cryp_k[5]; - CRYP->K3LR = cryp->cryp_k[6]; - CRYP->K3RR = cryp->cryp_k[7]; - - /* Setting up then starting operation.*/ - cr = CRYP->CR; - cr &= ~(CRYP_CR_KEYSIZE_Msk | CRYP_CR_ALGOMODE_Msk | CRYP_CR_ALGODIR_Msk); - cr |= cryp->cryp_ksize | algomode | CRYP_CR_CRYPEN; - CRYP->CR = cr; - - cryp->cryp_ktype = cryp_key_aes_encrypt; -} - -/** - * @brief Setting AES key for decryption. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] algomode algorithm field of CR register - */ -static inline void cryp_set_key_decrypt(CRYDriver *cryp, uint32_t algomode) { - uint32_t cr; - - /* Loading key data then doing transformation for decrypt.*/ - cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_KEY); - while ((CRYP->CR & CRYP_CR_CRYPEN) != 0U) { - } - - /* Setting up then starting operation.*/ - cr = CRYP->CR; - cr &= ~(CRYP_CR_KEYSIZE_Msk | CRYP_CR_ALGOMODE_Msk | CRYP_CR_ALGODIR_Msk); - cr |= cryp->cryp_ksize | algomode | CRYP_CR_ALGODIR | CRYP_CR_CRYPEN; - CRYP->CR = cr; - - cryp->cryp_ktype = cryp_key_aes_decrypt; -} - -/** - * @brief Setting IV. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] iv 128 bits initial vector - */ -static inline void cryp_set_iv(CRYDriver *cryp, const uint8_t *iv) { - - (void)cryp; - - CRYP->IV0LR = __REV(__UNALIGNED_UINT32_READ(&iv[0])); - CRYP->IV0RR = __REV(__UNALIGNED_UINT32_READ(&iv[4])); - CRYP->IV1LR = __REV(__UNALIGNED_UINT32_READ(&iv[8])); - CRYP->IV1RR = __REV(__UNALIGNED_UINT32_READ(&iv[12])); -} - -/** - * @brief Performs a CRYP operation using DMA. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] size size of both buffers, this number must be a - * multiple of 16 - * @param[in] in input buffer - * @param[out] out output buffer - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - */ -static cryerror_t cryp_do_transfer(CRYDriver *cryp, - size_t size, - const uint8_t *in, - uint8_t *out) { - uint32_t szw; - - szw = (uint32_t)(size / sizeof (uint32_t)); -#if STM32_CRY_CRYP_SIZE_THRESHOLD > 1 - if (size >= STM32_CRY_CRYP_SIZE_THRESHOLD) -#endif -#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 - { - /* DMA limitation.*/ - osalDbgCheck(size < 0x10000U * 4U); - - osalSysLock(); - - /* Preparing DMAs.*/ - dmaStreamSetTransactionSize(cryp->cryp_dma_in, szw); - dmaStreamSetTransactionSize(cryp->cryp_dma_out, szw); - dmaStreamSetMemory0(cryp->cryp_dma_in, in); - dmaStreamSetMemory0(cryp->cryp_dma_out, out); - dmaStreamEnable(cryp->cryp_dma_in); - dmaStreamEnable(cryp->cryp_dma_out); - - (void) osalThreadSuspendS(&cryp->cryp_tr); - - osalSysUnlock(); - } -#endif -#if STM32_CRY_CRYP_SIZE_THRESHOLD > 1 - else -#endif -#if STM32_CRY_CRYP_SIZE_THRESHOLD != 1 - { - uint32_t nr, nw; - - nr = 0U; - nw = 0U; - while (nw < szw) { - - if ((CRYP->SR & CRYP_SR_OFNE) != 0U) { - __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT); - out += 4; - nw++; - continue; /* Priority to output FIFO.*/ - } - - if ((nr < szw) && ((CRYP->SR & CRYP_SR_IFNF) != 0U)) { - CRYP->DR = __UNALIGNED_UINT32_READ(in); - in += 4; - nr++; - } - } - } -#endif - - /* Disabling unit.*/ - CRYP->CR &= ~CRYP_CR_CRYPEN; - - return CRY_NOERROR; -} - -/** - * @brief CRYP-IN DMA ISR. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void cry_lld_serve_cryp_in_interrupt(CRYDriver *cryp, uint32_t flags) { - - (void)cryp; - - /* DMA errors handling.*/ -#if defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { - STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp); - } -#endif -} - -/** - * @brief CRYP-OUT DMA ISR. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void cry_lld_serve_cryp_out_interrupt(CRYDriver *cryp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { - STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp); - } -#endif - - /* End buffer interrupt.*/ - if ((flags & STM32_DMA_ISR_TCIF) != 0U) { - - /* Clearing flags of the other stream too.*/ - dmaStreamClearInterrupt(cryp->cryp_dma_in); - - /* Resuming waiting thread.*/ - osalSysLockFromISR(); - osalThreadResumeI(&cryp->cryp_tr, MSG_OK); - osalSysUnlockFromISR(); - } -} -#endif - -#if (STM32_CRY_USE_HASH1 == TRUE) || defined (__DOXYGEN__) -#if (STM32_CRY_HASH_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__) -/** - * @brief HASH DMA ISR. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void cry_lld_serve_hash_interrupt(CRYDriver *cryp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_HASH_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { - STM32_CRY_HASH_DMA_ERROR_HOOK(cryp); - } -#endif - - /* End buffer interrupt.*/ - if ((flags & STM32_DMA_ISR_TCIF) != 0U) { - - /* Resuming waiting thread.*/ - osalSysLockFromISR(); - osalThreadResumeI(&cryp->hash_tr, MSG_OK); - osalSysUnlockFromISR(); - } -} -#endif -#endif - -/** - * @brief Pushes a series of words into the hash engine. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] n the number of words to be pushed - * @param[in] p pointer to the words buffer - */ -static void cry_lld_hash_push(CRYDriver *cryp, uint32_t n, const uint32_t *p) { - - (void)cryp; /* Not touched in some cases, needs this.*/ - - /* Data is processed in 32kB blocks because DMA size limitations.*/ - while (n > 0U) { - uint32_t chunk = n > 0x8000U ? 0x8000U : n; - n -= chunk; - -#if STM32_CRY_HASH_SIZE_THRESHOLD > 1 - if (chunk >= STM32_CRY_HASH_SIZE_THRESHOLD) -#endif -#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 - { - /* Setting up transfer.*/ - dmaStreamSetTransactionSize(cryp->hash_dma, chunk); - dmaStreamSetPeripheral(cryp->hash_dma, p); - p += chunk; - - osalSysLock(); - - /* Enabling DMA channel then HASH engine.*/ - dmaStreamEnable(cryp->hash_dma); - - /* Waiting for DMA operation completion.*/ - osalThreadSuspendS(&cryp->hash_tr); - - osalSysUnlock(); - } -#endif -#if STM32_CRY_HASH_SIZE_THRESHOLD > 1 - else -#endif -#if STM32_CRY_HASH_SIZE_THRESHOLD != 1 - { - /* Small chunk, just pushing data without touching DMA.*/ - do { - HASH->DIN = *p++; - chunk--; - } while (chunk > 0U); - } -#endif - } - -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level crypto driver initialization. - * - * @notapi - */ -void cry_lld_init(void) { - -#if STM32_CRY_ENABLED1 - cryObjectInit(&CRYD1); - -#if STM32_CRY_USE_CRYP1 -#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 - CRYD1.cryp_tr = NULL; - CRYD1.cryp_dma_in = NULL; - CRYD1.cryp_dma_out = NULL; -#endif -#endif - -#if STM32_CRY_USE_HASH1 -#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 - CRYD1.hash_tr = NULL; - CRYD1.hash_dma = NULL; -#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */ -#endif /* STM32_CRY_USE_HASH1 */ - -#endif /* STM32_CRY_ENABLED1 */ -} - -/** - * @brief Configures and activates the crypto peripheral. - * - * @param[in] cryp pointer to the @p CRYDriver object - * - * @notapi - */ -void cry_lld_start(CRYDriver *cryp) { - - if (cryp->state == CRY_STOP) { - -#if STM32_CRY_ENABLED1 - if (&CRYD1 == cryp) { -#if STM32_CRY_USE_CRYP1 == TRUE -#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 - /* Allocating DMA channels.*/ - cryp->cryp_dma_in = dmaStreamAllocI(STM32_CRY_CRYP1_IN_DMA_STREAM, - STM32_CRY_CRYP1_IRQ_PRIORITY, - (stm32_dmaisr_t)cry_lld_serve_cryp_in_interrupt, - (void *)cryp); - osalDbgAssert(cryp->cryp_dma_in != NULL, "unable to allocate stream"); - cryp->cryp_dma_out = dmaStreamAllocI(STM32_CRY_CRYP1_OUT_DMA_STREAM, - STM32_CRY_CRYP1_IRQ_PRIORITY, - (stm32_dmaisr_t)cry_lld_serve_cryp_out_interrupt, - (void *)cryp); - osalDbgAssert(cryp->cryp_dma_out != NULL, "unable to allocate stream"); - - /* Preparing the DMA channels.*/ - dmaStreamSetMode(cryp->cryp_dma_in, - STM32_DMA_CR_CHSEL(CRYP1_IN_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_CRY_CRYP1_IN_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE); - dmaStreamSetMode(cryp->cryp_dma_out, - STM32_DMA_CR_CHSEL(CRYP1_OUT_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | - STM32_DMA_CR_TCIE); - dmaStreamSetPeripheral(cryp->cryp_dma_in, &CRYP->DR); - dmaStreamSetPeripheral(cryp->cryp_dma_out, &CRYP->DOUT); - dmaStreamSetFIFO(cryp->cryp_dma_in, STM32_DMA_FCR_DMDIS); - dmaStreamSetFIFO(cryp->cryp_dma_out, STM32_DMA_FCR_DMDIS); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(cryp->cryp_dma_in, STM32_DMAMUX1_CRYP_IN); - dmaSetRequestSource(cryp->cryp_dma_out, STM32_DMAMUX1_CRYP_OUT); -#endif -#endif /* STM32_CRY_CRYP_SIZE_THRESHOLD != 0 */ - rccEnableCRYP(true); -#endif /* STM32_CRY_USE_CRYP1 == TRUE */ - -#if STM32_CRY_USE_HASH1 == TRUE -#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 - cryp->hash_dma = dmaStreamAllocI(STM32_CRY_HASH1_DMA_STREAM, - STM32_CRY_HASH1_IRQ_PRIORITY, - (stm32_dmaisr_t)cry_lld_serve_hash_interrupt, - (void *)cryp); - osalDbgAssert(cryp->hash_dma != NULL, "unable to allocate stream"); - - /* Preparing the DMA channel.*/ - dmaStreamSetMode(cryp->hash_dma, - STM32_DMA_CR_CHSEL(HASH1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_CRY_HASH1_DMA_PRIORITY) | - STM32_DMA_CR_PINC | STM32_DMA_CR_DIR_M2M | - STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | - STM32_DMA_CR_TCIE); - dmaStreamSetMemory0(cryp->hash_dma, &HASH->DIN); - dmaStreamSetFIFO(cryp->hash_dma, STM32_DMA_FCR_DMDIS); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(cryp->hash_dma, STM32_DMAMUX1_HASH_IN); -#endif -#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */ - rccEnableHASH(true); -#endif /* STM32_CRY_USE_HASH1 == TRUE */ - } -#endif - } - - /* Resetting trasient key data.*/ - cryp->cryp_ktype = cryp_key_none; - cryp->cryp_ksize = 0U; - cryp->cryp_k[0] = 0U; - cryp->cryp_k[1] = 0U; - cryp->cryp_k[2] = 0U; - cryp->cryp_k[3] = 0U; - cryp->cryp_k[4] = 0U; - cryp->cryp_k[5] = 0U; - cryp->cryp_k[6] = 0U; - cryp->cryp_k[7] = 0U; - -#if STM32_CRY_USE_CRYP1 - /* CRYP setup.*/ - CRYP->CR = CRYP_CR_DATATYPE_1; - CRYP->DMACR = CRYP_DMACR_DIEN | CRYP_DMACR_DOEN; -#endif - -#if STM32_CRY_USE_HASH1 - /* HASH setup and enable.*/ -#endif -} - -/** - * @brief Deactivates the crypto peripheral. - * - * @param[in] cryp pointer to the @p CRYDriver object - * - * @notapi - */ -void cry_lld_stop(CRYDriver *cryp) { - - if (cryp->state == CRY_READY) { - - /* Resetting CRYP.*/ - CRYP->CR = 0U; - CRYP->DMACR = 0U; - -#if STM32_CRY_ENABLED1 - if (&CRYD1 == cryp) { -#if STM32_CRY_USE_CRYP1 -#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 - dmaStreamFreeI(cryp->cryp_dma_in); - dmaStreamFreeI(cryp->cryp_dma_out); - cryp->cryp_dma_in = NULL; - cryp->cryp_dma_out = NULL; -#endif - rccDisableCRYP(); -#endif - -#if STM32_CRY_USE_HASH1 -#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 - dmaStreamFreeI(cryp->hash_dma); - cryp->hash_dma = NULL; -#endif - rccDisableHASH(); -#endif - } -#endif - } -} - -#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Initializes the AES transient key. - * @note It is the underlying implementation to decide which key sizes are - * allowable. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] size key size in bytes - * @param[in] keyp pointer to the key data - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported. - * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for - * the specified algorithm. - * - * @notapi - */ -cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp, - size_t size, - const uint8_t *keyp) { - - /* Fetching key data.*/ - if (size == (size_t)32) { - cryp->cryp_ksize = CRYP_CR_KEYSIZE_1; - cryp->cryp_k[0] = __REV(__UNALIGNED_UINT32_READ(&keyp[0])); - cryp->cryp_k[1] = __REV(__UNALIGNED_UINT32_READ(&keyp[4])); - cryp->cryp_k[2] = __REV(__UNALIGNED_UINT32_READ(&keyp[8])); - cryp->cryp_k[3] = __REV(__UNALIGNED_UINT32_READ(&keyp[12])); - cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16])); - cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20])); - cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24])); - cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28])); - } - else if (size == (size_t)24) { - cryp->cryp_ksize = CRYP_CR_KEYSIZE_0; - cryp->cryp_k[0] = 0U; - cryp->cryp_k[1] = 0U; - cryp->cryp_k[2] = __REV(__UNALIGNED_UINT32_READ(&keyp[8])); - cryp->cryp_k[3] = __REV(__UNALIGNED_UINT32_READ(&keyp[12])); - cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16])); - cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20])); - cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24])); - cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28])); - } - else if (size == (size_t)16) { - cryp->cryp_ksize = 0U; - cryp->cryp_k[0] = 0U; - cryp->cryp_k[1] = 0U; - cryp->cryp_k[2] = 0U; - cryp->cryp_k[3] = 0U; - cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16])); - cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20])); - cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24])); - cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28])); - } - else { - return CRY_ERR_INV_KEY_SIZE; - } - - return CRY_NOERROR; -} - -/** - * @brief Encryption of a single block using AES. - * @note The implementation of this function must guarantee that it can - * be called from any context. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out) { - unsigned i; - - /* Only key zero is supported.*/ - if (key_id != 0U) { - return CRY_ERR_INV_KEY_ID; - } - - /* Setting the stored key.*/ - if (cryp->cryp_ktype != cryp_key_aes_encrypt) { - cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); - } - - /* Pushing the AES block in the FIFO, it is assumed to be empty.*/ - CRYP->DR = __UNALIGNED_UINT32_READ(&in[0]); - CRYP->DR = __UNALIGNED_UINT32_READ(&in[4]); - CRYP->DR = __UNALIGNED_UINT32_READ(&in[8]); - CRYP->DR = __UNALIGNED_UINT32_READ(&in[12]); - - /* Reading the result.*/ - for (i = 0U; i < 4; i++, out += 4) { - while ((CRYP->SR & CRYP_SR_OFNE) == 0U) { - } - __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT); - } - - /* Disabling unit.*/ - CRYP->CR &= ~CRYP_CR_CRYPEN; - - return CRY_NOERROR; -} - -/** - * @brief Decryption of a single block using AES. - * @note The implementation of this function must guarantee that it can - * be called from any context. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] in buffer containing the input ciphertext - * @param[out] out buffer for the output plaintext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out) { - unsigned i; - - /* Only key zero is supported.*/ - if (key_id != 0U) { - return CRY_ERR_INV_KEY_ID; - } - - /* Setting the stored key.*/ - if (cryp->cryp_ktype != cryp_key_aes_decrypt) { - cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); - } - - /* Pushing the AES block in the FIFO, it is assumed to be empty.*/ - CRYP->DR = __UNALIGNED_UINT32_READ(&in[0]); - CRYP->DR = __UNALIGNED_UINT32_READ(&in[4]); - CRYP->DR = __UNALIGNED_UINT32_READ(&in[8]); - CRYP->DR = __UNALIGNED_UINT32_READ(&in[12]); - - /* Reading the result.*/ - for (i = 0U; i < 4; i++, out += 4) { - while ((CRYP->SR & CRYP_SR_OFNE) == 0U) { - } - __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT); - } - - /* Disabling unit.*/ - CRYP->CR &= ~CRYP_CR_CRYPEN; - - return CRY_NOERROR; -} -#endif - -#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using AES-ECB. - * @note The function operates on data buffers whose length is a multiple - * of an AES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers, this number must be a - * multiple of 16 - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out) { - - /* Only key zero is supported.*/ - if (key_id != 0U) { - return CRY_ERR_INV_KEY_ID; - } - - /* Setting the stored key.*/ - if (cryp->cryp_ktype != cryp_key_aes_encrypt) { - cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); - } - - return cryp_do_transfer(cryp, size, in, out); -} - -/** - * @brief Decryption operation using AES-ECB. - * @note The function operates on data buffers whose length is a multiple - * of an AES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers, this number must be a - * multiple of 16 - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out) { - - /* Only key zero is supported.*/ - if (key_id != 0U) { - return CRY_ERR_INV_KEY_ID; - } - - /* Setting the stored key.*/ - if (cryp->cryp_ktype != cryp_key_aes_decrypt) { - cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); - } - - return cryp_do_transfer(cryp, size, in, out); -} -#endif - -#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using AES-CBC. - * @note The function operates on data buffers whose length is a multiple - * of an AES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers, this number must be a - * multiple of 16 - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @param[in] iv 128 bits initial vector - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - /* Only key zero is supported.*/ - if (key_id != 0U) { - return CRY_ERR_INV_KEY_ID; - } - - /* Setting the stored key and IV.*/ - cryp_set_iv(cryp, iv); - if (cryp->cryp_ktype != cryp_key_aes_encrypt) { - cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_CBC); - } - - return cryp_do_transfer(cryp, size, in, out); -} - -/** - * @brief Decryption operation using AES-CBC. - * @note The function operates on data buffers whose length is a multiple - * of an AES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers, this number must be a - * multiple of 16 - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @param[in] iv 128 bits initial vector - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - /* Only key zero is supported.*/ - if (key_id != 0U) { - return CRY_ERR_INV_KEY_ID; - } - - /* Setting the stored key and IV.*/ - cryp_set_iv(cryp, iv); - if (cryp->cryp_ktype != cryp_key_aes_decrypt) { - cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_CBC); - } - - return cryp_do_transfer(cryp, size, in, out); -} -#endif - -#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using AES-CFB. - * @note This is a stream cipher, there are no size restrictions. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @param[in] iv 128 bits initial vector - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - (void)iv; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Decryption operation using AES-CFB. - * @note This is a stream cipher, there are no size restrictions. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @param[in] iv 128 bits initial vector - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - (void)iv; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using AES-CTR. - * @note This is a stream cipher, there are no size restrictions. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @param[in] iv 128 bits initial vector + counter, it contains - * a 96 bits IV and a 32 bits counter - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - (void)iv; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Decryption operation using AES-CTR. - * @note This is a stream cipher, there are no size restrictions. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of both buffers - * @param[in] in buffer containing the input ciphertext - * @param[out] out buffer for the output plaintext - * @param[in] iv 128 bits initial vector + counter, it contains - * a 96 bits IV and a 32 bits counter - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - (void)iv; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using AES-GCM. - * @note This is a stream cipher, there are no size restrictions. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] auth_size size of the data buffer to be authenticated - * @param[in] auth_in buffer containing the data to be authenticated - * @param[in] text_size size of the text buffer - * @param[in] text_in buffer containing the input plaintext - * @param[out] text_out buffer for the output ciphertext - * @param[in] iv 128 bits input vector - * @param[in] tag_size size of the authentication tag, this number - * must be between 1 and 16 - * @param[out] tag_out buffer for the generated authentication tag - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp, - crykey_t key_id, - size_t auth_size, - const uint8_t *auth_in, - size_t text_size, - const uint8_t *text_in, - uint8_t *text_out, - const uint8_t *iv, - size_t tag_size, - uint8_t *tag_out) { - - (void)cryp; - (void)key_id; - (void)auth_size; - (void)auth_in; - (void)text_size; - (void)text_in; - (void)text_out; - (void)iv; - (void)tag_size; - (void)tag_out; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Decryption operation using AES-GCM. - * @note This is a stream cipher, there are no size restrictions. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] auth_size size of the data buffer to be authenticated - * @param[in] auth_in buffer containing the data to be authenticated - * @param[in] text_size size of the text buffer - * @param[in] text_in buffer containing the input plaintext - * @param[out] text_out buffer for the output ciphertext - * @param[in] iv 128 bits input vector - * @param[in] tag_size size of the authentication tag, this number - * must be between 1 and 16 - * @param[in] tag_in buffer for the generated authentication tag - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_AUTH_FAILED authentication failed - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp, - crykey_t key_id, - size_t auth_size, - const uint8_t *auth_in, - size_t text_size, - const uint8_t *text_in, - uint8_t *text_out, - const uint8_t *iv, - size_t tag_size, - const uint8_t *tag_in) { - - (void)cryp; - (void)key_id; - (void)auth_size; - (void)auth_in; - (void)text_size; - (void)text_in; - (void)text_out; - (void)iv; - (void)tag_size; - (void)tag_in; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Initializes the DES transient key. - * @note It is the underlying implementation to decide which key sizes are - * allowable. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] size key size in bytes - * @param[in] keyp pointer to the key data - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported. - * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for - * the specified algorithm. - * - * @notapi - */ -cryerror_t cry_lld_des_loadkey(CRYDriver *cryp, - size_t size, - const uint8_t *keyp) { - - (void)cryp; - (void)size; - (void)keyp; - - return CRY_NOERROR; -} - -/** - * @brief Encryption of a single block using (T)DES. - * @note The implementation of this function must guarantee that it can - * be called from any context. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out) { - - (void)cryp; - (void)key_id; - (void)in; - (void)out; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Decryption of a single block using (T)DES. - * @note The implementation of this function must guarantee that it can - * be called from any context. - * - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] in buffer containing the input ciphertext - * @param[out] out buffer for the output plaintext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out) { - - (void)cryp; - (void)key_id; - (void)in; - (void)out; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using (T)DES-ECB. - * @note The function operates on data buffers whose length is a multiple - * of an DES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of the plaintext buffer, this number must - * be a multiple of 8 - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Decryption operation using (T)DES-ECB. - * @note The function operates on data buffers whose length is a multiple - * of an DES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of the plaintext buffer, this number must - * be a multiple of 8 - * @param[in] in buffer containing the input ciphertext - * @param[out] out buffer for the output plaintext - * @return T he operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__) -/** - * @brief Encryption operation using (T)DES-CBC. - * @note The function operates on data buffers whose length is a multiple - * of an DES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of the plaintext buffer, this number must - * be a multiple of 8 - * @param[in] in buffer containing the input plaintext - * @param[out] out buffer for the output ciphertext - * @param[in] iv 64 bits input vector - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - (void)iv; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Decryption operation using (T)DES-CBC. - * @note The function operates on data buffers whose length is a multiple - * of an DES block, this means that padding must be done by the - * caller. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] key_id the key to be used for the operation, zero is - * the transient key, other values are keys stored - * in an unspecified way - * @param[in] size size of the plaintext buffer, this number must - * be a multiple of 8 - * @param[in] in buffer containing the input ciphertext - * @param[out] out buffer for the output plaintext - * @param[in] iv 64 bits input vector - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. - * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid - * or refers to an empty key slot. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv) { - - (void)cryp; - (void)key_id; - (void)size; - (void)in; - (void)out; - (void)iv; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Hash initialization using SHA1. - * @note Use of this algorithm is not recommended because proven weak. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[out] sha1ctxp pointer to a SHA1 context to be initialized - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp) { - - (void)cryp; - (void)sha1ctxp; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash update using SHA1. - * @note Use of this algorithm is not recommended because proven weak. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] sha1ctxp pointer to a SHA1 context - * @param[in] size size of input buffer - * @param[in] in buffer containing the input text - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp, - size_t size, const uint8_t *in) { - - (void)cryp; - (void)sha1ctxp; - (void)size; - (void)in; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash finalization using SHA1. - * @note Use of this algorithm is not recommended because proven weak. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] sha1ctxp pointer to a SHA1 context - * @param[out] out 160 bits output buffer - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp, - uint8_t *out) { - - (void)cryp; - (void)sha1ctxp; - (void)out; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Hash initialization using SHA256. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[out] sha256ctxp pointer to a SHA256 context to be initialized - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp) { - - (void)cryp; - - /* Initializing context structure.*/ - sha256ctxp->last_data = 0U; - sha256ctxp->last_size = 0U; - - /* Initializing operation.*/ - HASH->CR = /*HASH_CR_MDMAT |*/ HASH_CR_ALGO_1 | HASH_CR_ALGO_0 | - HASH_CR_DATATYPE_1 | HASH_CR_INIT; - - return CRY_NOERROR; -} - -/** - * @brief Hash update using SHA256. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] sha256ctxp pointer to a SHA256 context - * @param[in] size size of input buffer - * @param[in] in buffer containing the input text - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp, - size_t size, const uint8_t *in) { - const uint32_t *wp = (const uint32_t *)(const void *)in; - - /* This HW is unable to hash blocks that are not a multiple of 4 bytes - except for the last block in the stream which is handled in the - "final" function.*/ - if (sha256ctxp->last_size != 0U) { - return CRY_ERR_OP_FAILURE; - } - - /* Any unaligned data is deferred to the "final" function.*/ - sha256ctxp->last_size = 8U * (size % sizeof (uint32_t)); - if (sha256ctxp->last_size > 0U) { - sha256ctxp->last_data = wp[size / sizeof (uint32_t)]; - } - - /* Pushing data.*/ - cry_lld_hash_push(cryp, (uint32_t)(size / sizeof (uint32_t)), wp); - - return CRY_NOERROR; -} - -/** - * @brief Hash finalization using SHA256. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] sha256ctxp pointer to a SHA256 context - * @param[out] out 256 bits output buffer - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp, - uint8_t *out) { - uint32_t digest[8]; - - (void)cryp; - - if (sha256ctxp->last_size > 0U) { - HASH->DIN = sha256ctxp->last_data; - } - - /* Triggering final calculation and wait for result.*/ - HASH->SR = 0U; - HASH->STR = sha256ctxp->last_size; - HASH->STR = sha256ctxp->last_size | HASH_STR_DCAL; - while ((HASH->SR & HASH_SR_DCIS) == 0U) { - } - - /* Reading digest.*/ - digest[0] = HASH_DIGEST->HR[0]; - digest[1] = HASH_DIGEST->HR[1]; - digest[2] = HASH_DIGEST->HR[2]; - digest[3] = HASH_DIGEST->HR[3]; - digest[4] = HASH_DIGEST->HR[4]; - digest[5] = HASH_DIGEST->HR[5]; - digest[6] = HASH_DIGEST->HR[6]; - digest[7] = HASH_DIGEST->HR[7]; - memcpy((void *)out, (const void *)digest, sizeof digest); - - return CRY_NOERROR; -} -#endif - -#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Hash initialization using SHA512. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[out] sha512ctxp pointer to a SHA512 context to be initialized - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp) { - - (void)cryp; - (void)sha512ctxp; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash update using SHA512. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] sha512ctxp pointer to a SHA512 context - * @param[in] size size of input buffer - * @param[in] in buffer containing the input text - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp, - size_t size, const uint8_t *in) { - - (void)cryp; - (void)sha512ctxp; - (void)size; - (void)in; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash finalization using SHA512. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] sha512ctxp pointer to a SHA512 context - * @param[out] out 512 bits output buffer - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp, - uint8_t *out) { - - (void)cryp; - (void)sha512ctxp; - (void)out; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Initializes the HMAC transient key. - * @note It is the underlying implementation to decide which key sizes are - * allowable. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] size key size in bytes - * @param[in] keyp pointer to the key data - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported. - * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for - * the specified algorithm. - * - * @notapi - */ -cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp, - size_t size, - const uint8_t *keyp) { - - (void)cryp; - (void)size; - (void)keyp; - - return CRY_NOERROR; -} - -/** - * @brief Hash initialization using HMAC_SHA256. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[out] hmacsha256ctxp pointer to a HMAC_SHA256 context to be - * initialized - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp, - HMACSHA256Context *hmacsha256ctxp) { - - (void)cryp; - (void)hmacsha256ctxp; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash update using HMAC. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context - * @param[in] size size of input buffer - * @param[in] in buffer containing the input text - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp, - HMACSHA256Context *hmacsha256ctxp, - size_t size, - const uint8_t *in) { - - (void)cryp; - (void)hmacsha256ctxp; - (void)size; - (void)in; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash finalization using HMAC. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context - * @param[out] out 256 bits output buffer - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp, - HMACSHA256Context *hmacsha256ctxp, - uint8_t *out) { - - (void)cryp; - (void)hmacsha256ctxp; - (void)out; - - return CRY_ERR_INV_ALGO; -} -#endif - -#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Hash initialization using HMAC_SHA512. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[out] hmacsha512ctxp pointer to a HMAC_SHA512 context to be - * initialized - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp, - HMACSHA512Context *hmacsha512ctxp) { - - (void)cryp; - (void)hmacsha512ctxp; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash update using HMAC. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context - * @param[in] size size of input buffer - * @param[in] in buffer containing the input text - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp, - HMACSHA512Context *hmacsha512ctxp, - size_t size, - const uint8_t *in) { - - (void)cryp; - (void)hmacsha512ctxp; - (void)size; - (void)in; - - return CRY_ERR_INV_ALGO; -} - -/** - * @brief Hash finalization using HMAC. - * - * @param[in] cryp pointer to the @p CRYDriver object - * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context - * @param[out] out 512 bits output buffer - * @return The operation status. - * @retval CRY_NOERROR if the operation succeeded. - * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this - * device instance. - * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation - * dependent. - * - * @notapi - */ -cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp, - HMACSHA512Context *hmacsha512ctxp, - uint8_t *out) { - - (void)cryp; - (void)hmacsha512ctxp; - (void)out; - - return CRY_ERR_INV_ALGO; -} -#endif - -#endif /* HAL_USE_CRY == TRUE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file CRYPv1/hal_crypto_lld.c + * @brief STM32 cryptographic subsystem low level driver source. + * + * @addtogroup CRYPTO + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define CRYP1_IN_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_CRY_CRYP1_IN_DMA_STREAM, \ + STM32_CRYP1_IN_DMA_CHN) + +#define CRYP1_OUT_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_CRY_CRYP1_OUT_DMA_STREAM, \ + STM32_CRYP1_OUT_DMA_CHN) + +#define HASH1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_CRY_HASH1_DMA_STREAM, \ + STM32_HASH1_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief CRY1 driver identifier.*/ +#if (STM32_CRY_ENABLED1 == TRUE) || defined(__DOXYGEN__) +CRYDriver CRYD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if (STM32_CRY_USE_CRYP1 == TRUE) || defined (__DOXYGEN__) +/** + * @brief Setting AES key for encryption. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] algomode algorithm mode field of CR register + */ +static inline void cryp_set_key_encrypt(CRYDriver *cryp, uint32_t algomode) { + uint32_t cr; + + /* Loading key data.*/ + CRYP->K0LR = cryp->cryp_k[0]; + CRYP->K0RR = cryp->cryp_k[1]; + CRYP->K1LR = cryp->cryp_k[2]; + CRYP->K1RR = cryp->cryp_k[3]; + CRYP->K2LR = cryp->cryp_k[4]; + CRYP->K2RR = cryp->cryp_k[5]; + CRYP->K3LR = cryp->cryp_k[6]; + CRYP->K3RR = cryp->cryp_k[7]; + + /* Setting up then starting operation.*/ + cr = CRYP->CR; + cr &= ~(CRYP_CR_KEYSIZE_Msk | CRYP_CR_ALGOMODE_Msk | CRYP_CR_ALGODIR_Msk); + cr |= cryp->cryp_ksize | algomode | CRYP_CR_CRYPEN; + CRYP->CR = cr; + + cryp->cryp_ktype = cryp_key_aes_encrypt; +} + +/** + * @brief Setting AES key for decryption. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] algomode algorithm field of CR register + */ +static inline void cryp_set_key_decrypt(CRYDriver *cryp, uint32_t algomode) { + uint32_t cr; + + /* Loading key data then doing transformation for decrypt.*/ + cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_KEY); + while ((CRYP->CR & CRYP_CR_CRYPEN) != 0U) { + } + + /* Setting up then starting operation.*/ + cr = CRYP->CR; + cr &= ~(CRYP_CR_KEYSIZE_Msk | CRYP_CR_ALGOMODE_Msk | CRYP_CR_ALGODIR_Msk); + cr |= cryp->cryp_ksize | algomode | CRYP_CR_ALGODIR | CRYP_CR_CRYPEN; + CRYP->CR = cr; + + cryp->cryp_ktype = cryp_key_aes_decrypt; +} + +/** + * @brief Setting IV. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] iv 128 bits initial vector + */ +static inline void cryp_set_iv(CRYDriver *cryp, const uint8_t *iv) { + + (void)cryp; + + CRYP->IV0LR = __REV(__UNALIGNED_UINT32_READ(&iv[0])); + CRYP->IV0RR = __REV(__UNALIGNED_UINT32_READ(&iv[4])); + CRYP->IV1LR = __REV(__UNALIGNED_UINT32_READ(&iv[8])); + CRYP->IV1RR = __REV(__UNALIGNED_UINT32_READ(&iv[12])); +} + +/** + * @brief Performs a CRYP operation using DMA. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] size size of both buffers, this number must be a + * multiple of 16 + * @param[in] in input buffer + * @param[out] out output buffer + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + */ +static cryerror_t cryp_do_transfer(CRYDriver *cryp, + size_t size, + const uint8_t *in, + uint8_t *out) { + uint32_t szw; + + szw = (uint32_t)(size / sizeof (uint32_t)); +#if STM32_CRY_CRYP_SIZE_THRESHOLD > 1 + if (size >= STM32_CRY_CRYP_SIZE_THRESHOLD) +#endif +#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 + { + /* DMA limitation.*/ + osalDbgCheck(size < 0x10000U * 4U); + + osalSysLock(); + + /* Preparing DMAs.*/ + dmaStreamSetTransactionSize(cryp->cryp_dma_in, szw); + dmaStreamSetTransactionSize(cryp->cryp_dma_out, szw); + dmaStreamSetMemory0(cryp->cryp_dma_in, in); + dmaStreamSetMemory0(cryp->cryp_dma_out, out); + dmaStreamEnable(cryp->cryp_dma_in); + dmaStreamEnable(cryp->cryp_dma_out); + + (void) osalThreadSuspendS(&cryp->cryp_tr); + + osalSysUnlock(); + } +#endif +#if STM32_CRY_CRYP_SIZE_THRESHOLD > 1 + else +#endif +#if STM32_CRY_CRYP_SIZE_THRESHOLD != 1 + { + uint32_t nr, nw; + + nr = 0U; + nw = 0U; + while (nw < szw) { + + if ((CRYP->SR & CRYP_SR_OFNE) != 0U) { + __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT); + out += 4; + nw++; + continue; /* Priority to output FIFO.*/ + } + + if ((nr < szw) && ((CRYP->SR & CRYP_SR_IFNF) != 0U)) { + CRYP->DR = __UNALIGNED_UINT32_READ(in); + in += 4; + nr++; + } + } + } +#endif + + /* Disabling unit.*/ + CRYP->CR &= ~CRYP_CR_CRYPEN; + + return CRY_NOERROR; +} + +/** + * @brief CRYP-IN DMA ISR. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void cry_lld_serve_cryp_in_interrupt(CRYDriver *cryp, uint32_t flags) { + + (void)cryp; + + /* DMA errors handling.*/ +#if defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { + STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp); + } +#endif +} + +/** + * @brief CRYP-OUT DMA ISR. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void cry_lld_serve_cryp_out_interrupt(CRYDriver *cryp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { + STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp); + } +#endif + + /* End buffer interrupt.*/ + if ((flags & STM32_DMA_ISR_TCIF) != 0U) { + + /* Clearing flags of the other stream too.*/ + dmaStreamClearInterrupt(cryp->cryp_dma_in); + + /* Resuming waiting thread.*/ + osalSysLockFromISR(); + osalThreadResumeI(&cryp->cryp_tr, MSG_OK); + osalSysUnlockFromISR(); + } +} +#endif + +#if (STM32_CRY_USE_HASH1 == TRUE) || defined (__DOXYGEN__) +#if (STM32_CRY_HASH_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__) +/** + * @brief HASH DMA ISR. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void cry_lld_serve_hash_interrupt(CRYDriver *cryp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_HASH_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { + STM32_CRY_HASH_DMA_ERROR_HOOK(cryp); + } +#endif + + /* End buffer interrupt.*/ + if ((flags & STM32_DMA_ISR_TCIF) != 0U) { + + /* Resuming waiting thread.*/ + osalSysLockFromISR(); + osalThreadResumeI(&cryp->hash_tr, MSG_OK); + osalSysUnlockFromISR(); + } +} +#endif +#endif + +/** + * @brief Pushes a series of words into the hash engine. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] n the number of words to be pushed + * @param[in] p pointer to the words buffer + */ +static void cry_lld_hash_push(CRYDriver *cryp, uint32_t n, const uint32_t *p) { + + (void)cryp; /* Not touched in some cases, needs this.*/ + + /* Data is processed in 32kB blocks because DMA size limitations.*/ + while (n > 0U) { + uint32_t chunk = n > 0x8000U ? 0x8000U : n; + n -= chunk; + +#if STM32_CRY_HASH_SIZE_THRESHOLD > 1 + if (chunk >= STM32_CRY_HASH_SIZE_THRESHOLD) +#endif +#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 + { + /* Setting up transfer.*/ + dmaStreamSetTransactionSize(cryp->hash_dma, chunk); + dmaStreamSetPeripheral(cryp->hash_dma, p); + p += chunk; + + osalSysLock(); + + /* Enabling DMA channel then HASH engine.*/ + dmaStreamEnable(cryp->hash_dma); + + /* Waiting for DMA operation completion.*/ + osalThreadSuspendS(&cryp->hash_tr); + + osalSysUnlock(); + } +#endif +#if STM32_CRY_HASH_SIZE_THRESHOLD > 1 + else +#endif +#if STM32_CRY_HASH_SIZE_THRESHOLD != 1 + { + /* Small chunk, just pushing data without touching DMA.*/ + do { + HASH->DIN = *p++; + chunk--; + } while (chunk > 0U); + } +#endif + } + +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level crypto driver initialization. + * + * @notapi + */ +void cry_lld_init(void) { + +#if STM32_CRY_ENABLED1 + cryObjectInit(&CRYD1); + +#if STM32_CRY_USE_CRYP1 +#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 + CRYD1.cryp_tr = NULL; + CRYD1.cryp_dma_in = NULL; + CRYD1.cryp_dma_out = NULL; +#endif +#endif + +#if STM32_CRY_USE_HASH1 +#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 + CRYD1.hash_tr = NULL; + CRYD1.hash_dma = NULL; +#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */ +#endif /* STM32_CRY_USE_HASH1 */ + +#endif /* STM32_CRY_ENABLED1 */ +} + +/** + * @brief Configures and activates the crypto peripheral. + * + * @param[in] cryp pointer to the @p CRYDriver object + * + * @notapi + */ +void cry_lld_start(CRYDriver *cryp) { + + if (cryp->state == CRY_STOP) { + +#if STM32_CRY_ENABLED1 + if (&CRYD1 == cryp) { +#if STM32_CRY_USE_CRYP1 == TRUE +#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 + /* Allocating DMA channels.*/ + cryp->cryp_dma_in = dmaStreamAllocI(STM32_CRY_CRYP1_IN_DMA_STREAM, + STM32_CRY_CRYP1_IRQ_PRIORITY, + (stm32_dmaisr_t)cry_lld_serve_cryp_in_interrupt, + (void *)cryp); + osalDbgAssert(cryp->cryp_dma_in != NULL, "unable to allocate stream"); + cryp->cryp_dma_out = dmaStreamAllocI(STM32_CRY_CRYP1_OUT_DMA_STREAM, + STM32_CRY_CRYP1_IRQ_PRIORITY, + (stm32_dmaisr_t)cry_lld_serve_cryp_out_interrupt, + (void *)cryp); + osalDbgAssert(cryp->cryp_dma_out != NULL, "unable to allocate stream"); + + /* Preparing the DMA channels.*/ + dmaStreamSetMode(cryp->cryp_dma_in, + STM32_DMA_CR_CHSEL(CRYP1_IN_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_CRY_CRYP1_IN_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE); + dmaStreamSetMode(cryp->cryp_dma_out, + STM32_DMA_CR_CHSEL(CRYP1_OUT_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | + STM32_DMA_CR_TCIE); + dmaStreamSetPeripheral(cryp->cryp_dma_in, &CRYP->DR); + dmaStreamSetPeripheral(cryp->cryp_dma_out, &CRYP->DOUT); + dmaStreamSetFIFO(cryp->cryp_dma_in, STM32_DMA_FCR_DMDIS); + dmaStreamSetFIFO(cryp->cryp_dma_out, STM32_DMA_FCR_DMDIS); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(cryp->cryp_dma_in, STM32_DMAMUX1_CRYP_IN); + dmaSetRequestSource(cryp->cryp_dma_out, STM32_DMAMUX1_CRYP_OUT); +#endif +#endif /* STM32_CRY_CRYP_SIZE_THRESHOLD != 0 */ + rccEnableCRYP(true); +#endif /* STM32_CRY_USE_CRYP1 == TRUE */ + +#if STM32_CRY_USE_HASH1 == TRUE +#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 + cryp->hash_dma = dmaStreamAllocI(STM32_CRY_HASH1_DMA_STREAM, + STM32_CRY_HASH1_IRQ_PRIORITY, + (stm32_dmaisr_t)cry_lld_serve_hash_interrupt, + (void *)cryp); + osalDbgAssert(cryp->hash_dma != NULL, "unable to allocate stream"); + + /* Preparing the DMA channel.*/ + dmaStreamSetMode(cryp->hash_dma, + STM32_DMA_CR_CHSEL(HASH1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_CRY_HASH1_DMA_PRIORITY) | + STM32_DMA_CR_PINC | STM32_DMA_CR_DIR_M2M | + STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | + STM32_DMA_CR_TCIE); + dmaStreamSetMemory0(cryp->hash_dma, &HASH->DIN); + dmaStreamSetFIFO(cryp->hash_dma, STM32_DMA_FCR_DMDIS); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(cryp->hash_dma, STM32_DMAMUX1_HASH_IN); +#endif +#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */ + rccEnableHASH(true); +#endif /* STM32_CRY_USE_HASH1 == TRUE */ + } +#endif + } + + /* Resetting trasient key data.*/ + cryp->cryp_ktype = cryp_key_none; + cryp->cryp_ksize = 0U; + cryp->cryp_k[0] = 0U; + cryp->cryp_k[1] = 0U; + cryp->cryp_k[2] = 0U; + cryp->cryp_k[3] = 0U; + cryp->cryp_k[4] = 0U; + cryp->cryp_k[5] = 0U; + cryp->cryp_k[6] = 0U; + cryp->cryp_k[7] = 0U; + +#if STM32_CRY_USE_CRYP1 + /* CRYP setup.*/ + CRYP->CR = CRYP_CR_DATATYPE_1; + CRYP->DMACR = CRYP_DMACR_DIEN | CRYP_DMACR_DOEN; +#endif + +#if STM32_CRY_USE_HASH1 + /* HASH setup and enable.*/ +#endif +} + +/** + * @brief Deactivates the crypto peripheral. + * + * @param[in] cryp pointer to the @p CRYDriver object + * + * @notapi + */ +void cry_lld_stop(CRYDriver *cryp) { + + if (cryp->state == CRY_READY) { + + /* Resetting CRYP.*/ + CRYP->CR = 0U; + CRYP->DMACR = 0U; + +#if STM32_CRY_ENABLED1 + if (&CRYD1 == cryp) { +#if STM32_CRY_USE_CRYP1 +#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0 + dmaStreamFreeI(cryp->cryp_dma_in); + dmaStreamFreeI(cryp->cryp_dma_out); + cryp->cryp_dma_in = NULL; + cryp->cryp_dma_out = NULL; +#endif + rccDisableCRYP(); +#endif + +#if STM32_CRY_USE_HASH1 +#if STM32_CRY_HASH_SIZE_THRESHOLD != 0 + dmaStreamFreeI(cryp->hash_dma); + cryp->hash_dma = NULL; +#endif + rccDisableHASH(); +#endif + } +#endif + } +} + +#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Initializes the AES transient key. + * @note It is the underlying implementation to decide which key sizes are + * allowable. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] size key size in bytes + * @param[in] keyp pointer to the key data + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported. + * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for + * the specified algorithm. + * + * @notapi + */ +cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp, + size_t size, + const uint8_t *keyp) { + + /* Fetching key data.*/ + if (size == (size_t)32) { + cryp->cryp_ksize = CRYP_CR_KEYSIZE_1; + cryp->cryp_k[0] = __REV(__UNALIGNED_UINT32_READ(&keyp[0])); + cryp->cryp_k[1] = __REV(__UNALIGNED_UINT32_READ(&keyp[4])); + cryp->cryp_k[2] = __REV(__UNALIGNED_UINT32_READ(&keyp[8])); + cryp->cryp_k[3] = __REV(__UNALIGNED_UINT32_READ(&keyp[12])); + cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16])); + cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20])); + cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24])); + cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28])); + } + else if (size == (size_t)24) { + cryp->cryp_ksize = CRYP_CR_KEYSIZE_0; + cryp->cryp_k[0] = 0U; + cryp->cryp_k[1] = 0U; + cryp->cryp_k[2] = __REV(__UNALIGNED_UINT32_READ(&keyp[8])); + cryp->cryp_k[3] = __REV(__UNALIGNED_UINT32_READ(&keyp[12])); + cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16])); + cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20])); + cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24])); + cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28])); + } + else if (size == (size_t)16) { + cryp->cryp_ksize = 0U; + cryp->cryp_k[0] = 0U; + cryp->cryp_k[1] = 0U; + cryp->cryp_k[2] = 0U; + cryp->cryp_k[3] = 0U; + cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16])); + cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20])); + cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24])); + cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28])); + } + else { + return CRY_ERR_INV_KEY_SIZE; + } + + return CRY_NOERROR; +} + +/** + * @brief Encryption of a single block using AES. + * @note The implementation of this function must guarantee that it can + * be called from any context. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out) { + unsigned i; + + /* Only key zero is supported.*/ + if (key_id != 0U) { + return CRY_ERR_INV_KEY_ID; + } + + /* Setting the stored key.*/ + if (cryp->cryp_ktype != cryp_key_aes_encrypt) { + cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); + } + + /* Pushing the AES block in the FIFO, it is assumed to be empty.*/ + CRYP->DR = __UNALIGNED_UINT32_READ(&in[0]); + CRYP->DR = __UNALIGNED_UINT32_READ(&in[4]); + CRYP->DR = __UNALIGNED_UINT32_READ(&in[8]); + CRYP->DR = __UNALIGNED_UINT32_READ(&in[12]); + + /* Reading the result.*/ + for (i = 0U; i < 4; i++, out += 4) { + while ((CRYP->SR & CRYP_SR_OFNE) == 0U) { + } + __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT); + } + + /* Disabling unit.*/ + CRYP->CR &= ~CRYP_CR_CRYPEN; + + return CRY_NOERROR; +} + +/** + * @brief Decryption of a single block using AES. + * @note The implementation of this function must guarantee that it can + * be called from any context. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] in buffer containing the input ciphertext + * @param[out] out buffer for the output plaintext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out) { + unsigned i; + + /* Only key zero is supported.*/ + if (key_id != 0U) { + return CRY_ERR_INV_KEY_ID; + } + + /* Setting the stored key.*/ + if (cryp->cryp_ktype != cryp_key_aes_decrypt) { + cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); + } + + /* Pushing the AES block in the FIFO, it is assumed to be empty.*/ + CRYP->DR = __UNALIGNED_UINT32_READ(&in[0]); + CRYP->DR = __UNALIGNED_UINT32_READ(&in[4]); + CRYP->DR = __UNALIGNED_UINT32_READ(&in[8]); + CRYP->DR = __UNALIGNED_UINT32_READ(&in[12]); + + /* Reading the result.*/ + for (i = 0U; i < 4; i++, out += 4) { + while ((CRYP->SR & CRYP_SR_OFNE) == 0U) { + } + __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT); + } + + /* Disabling unit.*/ + CRYP->CR &= ~CRYP_CR_CRYPEN; + + return CRY_NOERROR; +} +#endif + +#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using AES-ECB. + * @note The function operates on data buffers whose length is a multiple + * of an AES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers, this number must be a + * multiple of 16 + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out) { + + /* Only key zero is supported.*/ + if (key_id != 0U) { + return CRY_ERR_INV_KEY_ID; + } + + /* Setting the stored key.*/ + if (cryp->cryp_ktype != cryp_key_aes_encrypt) { + cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); + } + + return cryp_do_transfer(cryp, size, in, out); +} + +/** + * @brief Decryption operation using AES-ECB. + * @note The function operates on data buffers whose length is a multiple + * of an AES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers, this number must be a + * multiple of 16 + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out) { + + /* Only key zero is supported.*/ + if (key_id != 0U) { + return CRY_ERR_INV_KEY_ID; + } + + /* Setting the stored key.*/ + if (cryp->cryp_ktype != cryp_key_aes_decrypt) { + cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB); + } + + return cryp_do_transfer(cryp, size, in, out); +} +#endif + +#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using AES-CBC. + * @note The function operates on data buffers whose length is a multiple + * of an AES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers, this number must be a + * multiple of 16 + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @param[in] iv 128 bits initial vector + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + /* Only key zero is supported.*/ + if (key_id != 0U) { + return CRY_ERR_INV_KEY_ID; + } + + /* Setting the stored key and IV.*/ + cryp_set_iv(cryp, iv); + if (cryp->cryp_ktype != cryp_key_aes_encrypt) { + cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_CBC); + } + + return cryp_do_transfer(cryp, size, in, out); +} + +/** + * @brief Decryption operation using AES-CBC. + * @note The function operates on data buffers whose length is a multiple + * of an AES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers, this number must be a + * multiple of 16 + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @param[in] iv 128 bits initial vector + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + /* Only key zero is supported.*/ + if (key_id != 0U) { + return CRY_ERR_INV_KEY_ID; + } + + /* Setting the stored key and IV.*/ + cryp_set_iv(cryp, iv); + if (cryp->cryp_ktype != cryp_key_aes_decrypt) { + cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_CBC); + } + + return cryp_do_transfer(cryp, size, in, out); +} +#endif + +#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using AES-CFB. + * @note This is a stream cipher, there are no size restrictions. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @param[in] iv 128 bits initial vector + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + (void)iv; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Decryption operation using AES-CFB. + * @note This is a stream cipher, there are no size restrictions. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @param[in] iv 128 bits initial vector + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + (void)iv; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using AES-CTR. + * @note This is a stream cipher, there are no size restrictions. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @param[in] iv 128 bits initial vector + counter, it contains + * a 96 bits IV and a 32 bits counter + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + (void)iv; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Decryption operation using AES-CTR. + * @note This is a stream cipher, there are no size restrictions. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of both buffers + * @param[in] in buffer containing the input ciphertext + * @param[out] out buffer for the output plaintext + * @param[in] iv 128 bits initial vector + counter, it contains + * a 96 bits IV and a 32 bits counter + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + (void)iv; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using AES-GCM. + * @note This is a stream cipher, there are no size restrictions. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] auth_size size of the data buffer to be authenticated + * @param[in] auth_in buffer containing the data to be authenticated + * @param[in] text_size size of the text buffer + * @param[in] text_in buffer containing the input plaintext + * @param[out] text_out buffer for the output ciphertext + * @param[in] iv 128 bits input vector + * @param[in] tag_size size of the authentication tag, this number + * must be between 1 and 16 + * @param[out] tag_out buffer for the generated authentication tag + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp, + crykey_t key_id, + size_t auth_size, + const uint8_t *auth_in, + size_t text_size, + const uint8_t *text_in, + uint8_t *text_out, + const uint8_t *iv, + size_t tag_size, + uint8_t *tag_out) { + + (void)cryp; + (void)key_id; + (void)auth_size; + (void)auth_in; + (void)text_size; + (void)text_in; + (void)text_out; + (void)iv; + (void)tag_size; + (void)tag_out; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Decryption operation using AES-GCM. + * @note This is a stream cipher, there are no size restrictions. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] auth_size size of the data buffer to be authenticated + * @param[in] auth_in buffer containing the data to be authenticated + * @param[in] text_size size of the text buffer + * @param[in] text_in buffer containing the input plaintext + * @param[out] text_out buffer for the output ciphertext + * @param[in] iv 128 bits input vector + * @param[in] tag_size size of the authentication tag, this number + * must be between 1 and 16 + * @param[in] tag_in buffer for the generated authentication tag + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_AUTH_FAILED authentication failed + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp, + crykey_t key_id, + size_t auth_size, + const uint8_t *auth_in, + size_t text_size, + const uint8_t *text_in, + uint8_t *text_out, + const uint8_t *iv, + size_t tag_size, + const uint8_t *tag_in) { + + (void)cryp; + (void)key_id; + (void)auth_size; + (void)auth_in; + (void)text_size; + (void)text_in; + (void)text_out; + (void)iv; + (void)tag_size; + (void)tag_in; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Initializes the DES transient key. + * @note It is the underlying implementation to decide which key sizes are + * allowable. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] size key size in bytes + * @param[in] keyp pointer to the key data + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported. + * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for + * the specified algorithm. + * + * @notapi + */ +cryerror_t cry_lld_des_loadkey(CRYDriver *cryp, + size_t size, + const uint8_t *keyp) { + + (void)cryp; + (void)size; + (void)keyp; + + return CRY_NOERROR; +} + +/** + * @brief Encryption of a single block using (T)DES. + * @note The implementation of this function must guarantee that it can + * be called from any context. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out) { + + (void)cryp; + (void)key_id; + (void)in; + (void)out; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Decryption of a single block using (T)DES. + * @note The implementation of this function must guarantee that it can + * be called from any context. + * + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] in buffer containing the input ciphertext + * @param[out] out buffer for the output plaintext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out) { + + (void)cryp; + (void)key_id; + (void)in; + (void)out; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using (T)DES-ECB. + * @note The function operates on data buffers whose length is a multiple + * of an DES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of the plaintext buffer, this number must + * be a multiple of 8 + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Decryption operation using (T)DES-ECB. + * @note The function operates on data buffers whose length is a multiple + * of an DES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of the plaintext buffer, this number must + * be a multiple of 8 + * @param[in] in buffer containing the input ciphertext + * @param[out] out buffer for the output plaintext + * @return T he operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__) +/** + * @brief Encryption operation using (T)DES-CBC. + * @note The function operates on data buffers whose length is a multiple + * of an DES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of the plaintext buffer, this number must + * be a multiple of 8 + * @param[in] in buffer containing the input plaintext + * @param[out] out buffer for the output ciphertext + * @param[in] iv 64 bits input vector + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + (void)iv; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Decryption operation using (T)DES-CBC. + * @note The function operates on data buffers whose length is a multiple + * of an DES block, this means that padding must be done by the + * caller. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] key_id the key to be used for the operation, zero is + * the transient key, other values are keys stored + * in an unspecified way + * @param[in] size size of the plaintext buffer, this number must + * be a multiple of 8 + * @param[in] in buffer containing the input ciphertext + * @param[out] out buffer for the output plaintext + * @param[in] iv 64 bits input vector + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation. + * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid + * or refers to an empty key slot. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv) { + + (void)cryp; + (void)key_id; + (void)size; + (void)in; + (void)out; + (void)iv; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Hash initialization using SHA1. + * @note Use of this algorithm is not recommended because proven weak. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[out] sha1ctxp pointer to a SHA1 context to be initialized + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp) { + + (void)cryp; + (void)sha1ctxp; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash update using SHA1. + * @note Use of this algorithm is not recommended because proven weak. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] sha1ctxp pointer to a SHA1 context + * @param[in] size size of input buffer + * @param[in] in buffer containing the input text + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp, + size_t size, const uint8_t *in) { + + (void)cryp; + (void)sha1ctxp; + (void)size; + (void)in; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash finalization using SHA1. + * @note Use of this algorithm is not recommended because proven weak. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] sha1ctxp pointer to a SHA1 context + * @param[out] out 160 bits output buffer + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp, + uint8_t *out) { + + (void)cryp; + (void)sha1ctxp; + (void)out; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Hash initialization using SHA256. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[out] sha256ctxp pointer to a SHA256 context to be initialized + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp) { + + (void)cryp; + + /* Initializing context structure.*/ + sha256ctxp->last_data = 0U; + sha256ctxp->last_size = 0U; + + /* Initializing operation.*/ + HASH->CR = /*HASH_CR_MDMAT |*/ HASH_CR_ALGO_1 | HASH_CR_ALGO_0 | + HASH_CR_DATATYPE_1 | HASH_CR_INIT; + + return CRY_NOERROR; +} + +/** + * @brief Hash update using SHA256. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] sha256ctxp pointer to a SHA256 context + * @param[in] size size of input buffer + * @param[in] in buffer containing the input text + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp, + size_t size, const uint8_t *in) { + const uint32_t *wp = (const uint32_t *)(const void *)in; + + /* This HW is unable to hash blocks that are not a multiple of 4 bytes + except for the last block in the stream which is handled in the + "final" function.*/ + if (sha256ctxp->last_size != 0U) { + return CRY_ERR_OP_FAILURE; + } + + /* Any unaligned data is deferred to the "final" function.*/ + sha256ctxp->last_size = 8U * (size % sizeof (uint32_t)); + if (sha256ctxp->last_size > 0U) { + sha256ctxp->last_data = wp[size / sizeof (uint32_t)]; + } + + /* Pushing data.*/ + cry_lld_hash_push(cryp, (uint32_t)(size / sizeof (uint32_t)), wp); + + return CRY_NOERROR; +} + +/** + * @brief Hash finalization using SHA256. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] sha256ctxp pointer to a SHA256 context + * @param[out] out 256 bits output buffer + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp, + uint8_t *out) { + uint32_t digest[8]; + + (void)cryp; + + if (sha256ctxp->last_size > 0U) { + HASH->DIN = sha256ctxp->last_data; + } + + /* Triggering final calculation and wait for result.*/ + HASH->SR = 0U; + HASH->STR = sha256ctxp->last_size; + HASH->STR = sha256ctxp->last_size | HASH_STR_DCAL; + while ((HASH->SR & HASH_SR_DCIS) == 0U) { + } + + /* Reading digest.*/ + digest[0] = HASH_DIGEST->HR[0]; + digest[1] = HASH_DIGEST->HR[1]; + digest[2] = HASH_DIGEST->HR[2]; + digest[3] = HASH_DIGEST->HR[3]; + digest[4] = HASH_DIGEST->HR[4]; + digest[5] = HASH_DIGEST->HR[5]; + digest[6] = HASH_DIGEST->HR[6]; + digest[7] = HASH_DIGEST->HR[7]; + memcpy((void *)out, (const void *)digest, sizeof digest); + + return CRY_NOERROR; +} +#endif + +#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Hash initialization using SHA512. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[out] sha512ctxp pointer to a SHA512 context to be initialized + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp) { + + (void)cryp; + (void)sha512ctxp; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash update using SHA512. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] sha512ctxp pointer to a SHA512 context + * @param[in] size size of input buffer + * @param[in] in buffer containing the input text + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp, + size_t size, const uint8_t *in) { + + (void)cryp; + (void)sha512ctxp; + (void)size; + (void)in; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash finalization using SHA512. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] sha512ctxp pointer to a SHA512 context + * @param[out] out 512 bits output buffer + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp, + uint8_t *out) { + + (void)cryp; + (void)sha512ctxp; + (void)out; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Initializes the HMAC transient key. + * @note It is the underlying implementation to decide which key sizes are + * allowable. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] size key size in bytes + * @param[in] keyp pointer to the key data + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported. + * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for + * the specified algorithm. + * + * @notapi + */ +cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp, + size_t size, + const uint8_t *keyp) { + + (void)cryp; + (void)size; + (void)keyp; + + return CRY_NOERROR; +} + +/** + * @brief Hash initialization using HMAC_SHA256. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[out] hmacsha256ctxp pointer to a HMAC_SHA256 context to be + * initialized + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp, + HMACSHA256Context *hmacsha256ctxp) { + + (void)cryp; + (void)hmacsha256ctxp; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash update using HMAC. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context + * @param[in] size size of input buffer + * @param[in] in buffer containing the input text + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp, + HMACSHA256Context *hmacsha256ctxp, + size_t size, + const uint8_t *in) { + + (void)cryp; + (void)hmacsha256ctxp; + (void)size; + (void)in; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash finalization using HMAC. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context + * @param[out] out 256 bits output buffer + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp, + HMACSHA256Context *hmacsha256ctxp, + uint8_t *out) { + + (void)cryp; + (void)hmacsha256ctxp; + (void)out; + + return CRY_ERR_INV_ALGO; +} +#endif + +#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Hash initialization using HMAC_SHA512. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[out] hmacsha512ctxp pointer to a HMAC_SHA512 context to be + * initialized + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp, + HMACSHA512Context *hmacsha512ctxp) { + + (void)cryp; + (void)hmacsha512ctxp; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash update using HMAC. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context + * @param[in] size size of input buffer + * @param[in] in buffer containing the input text + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp, + HMACSHA512Context *hmacsha512ctxp, + size_t size, + const uint8_t *in) { + + (void)cryp; + (void)hmacsha512ctxp; + (void)size; + (void)in; + + return CRY_ERR_INV_ALGO; +} + +/** + * @brief Hash finalization using HMAC. + * + * @param[in] cryp pointer to the @p CRYDriver object + * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context + * @param[out] out 512 bits output buffer + * @return The operation status. + * @retval CRY_NOERROR if the operation succeeded. + * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this + * device instance. + * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation + * dependent. + * + * @notapi + */ +cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp, + HMACSHA512Context *hmacsha512ctxp, + uint8_t *out) { + + (void)cryp; + (void)hmacsha512ctxp; + (void)out; + + return CRY_ERR_INV_ALGO; +} +#endif + +#endif /* HAL_USE_CRY == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h b/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h index 257d39624a..523ef03c8e 100644 --- a/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h +++ b/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h @@ -1,618 +1,618 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file CRYPv1/hal_cry_lld.h - * @brief STM32 cryptographic subsystem low level driver header. - * - * @addtogroup CRYPTO - * @{ - */ - -#ifndef HAL_CRYPTO_LLD_H -#define HAL_CRYPTO_LLD_H - -#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name STM32 configuration options - * @{ - */ -/** - * @brief CRYP1 driver enable switch. - * @details If set to @p TRUE the support for CRYP1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_CRY_USE_CRYP1) || defined(__DOXYGEN__) -#define STM32_CRY_USE_CRYP1 FALSE -#endif - -/** - * @brief HASH1 driver enable switch. - * @details If set to @p TRUE the support for HASH1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_CRY_USE_HASH1) || defined(__DOXYGEN__) -#define STM32_CRY_USE_HASH1 FALSE -#endif - -/** - * @brief CRYP1 interrupt priority level setting. - */ -#if !defined(STM32_CRY_CRYP1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CRY_CRYP1_IRQ_PRIORITY 9 -#endif - -/** - * @brief HASH1 interrupt priority level setting. - */ -#if !defined(STM32_CRY_HASH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CRY_HASH1_IRQ_PRIORITY 9 -#endif - -/** - * @brief HASH1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CRY_CRYP1_OUT_DMA_PRIORITY 0 -#endif - -/** - * @brief HASH1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_CRY_HASH1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CRY_HASH1_DMA_PRIORITY 0 -#endif - -/** - * @brief Minimum message size (in words) for DMA use. - * @note If set to zero then DMA is never used. - * @note If set to one then DMA is always used. - */ -#if !defined(STM32_CRY_HASH_SIZE_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_CRY_HASH_SIZE_THRESHOLD 1024 -#endif - -/** - * @brief Minimum text size (in bytes) for DMA use. - * @note If set to zero then DMA is never used. - * @note If set to one then DMA is always used. - */ -#if !defined(STM32_CRY_CRYP_SIZE_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_CRY_CRYP_SIZE_THRESHOLD 1024 -#endif - -/** - * @brief Hash DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_CRY_HASH_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_CRY_HASH_DMA_ERROR_HOOK(cryp) osalSysHalt("DMA failure") -#endif - -/** - * @brief CRYP DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if (STM32_CRY_USE_CRYP1 == TRUE) || (STM32_CRY_USE_HASH1 == TRUE) || \ - defined (__DOXYGEN__) -#define STM32_CRY_ENABLED1 TRUE -#else -#define STM32_CRY_ENABLED1 FALSE -#endif - -#if !defined (STM32_HAS_CRYP1) -#define STM32_HAS_CRYP1 FALSE -#endif - -#if !defined (STM32_HAS_HASH1) -#define STM32_HAS_HASH1 FALSE -#endif - -#if STM32_CRY_USE_CRYP1 && !STM32_HAS_CRYP1 -#error "CRYP1 not present in the selected device" -#endif - -#if STM32_CRY_USE_HASH1 && !STM32_HAS_HASH1 -#error "HASH1 not present in the selected device" -#endif - -#if !STM32_CRY_ENABLED1 -#error "CRY driver activated but no CRYP nor HASH peripheral assigned" -#endif - -#if STM32_CRY_USE_HASH1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_CRY_HASH1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to HASH1" -#endif - -#if STM32_CRY_USE_CRYP1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_CRY_CRYP1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to CRYP1" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if !defined(STM32_CRY_HASH1_DMA_STREAM) -#error "HASH1 DMA streams not defined" -#endif - -/* Sanity checks on DMA streams settings in mcuconf.h.*/ -#if STM32_CRY_USE_HASH1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_CRY_HASH1_DMA_STREAM) -#error "Invalid DMA stream assigned to HASH1" -#endif - -/* Devices without DMAMUX require an additional check.*/ -#if !STM32_DMA_SUPPORTS_DMAMUX -#if STM32_CRY_USE_CRYP1 && \ - !STM32_DMA_IS_VALID_ID(STM32_CRY_CRYP1_IN_DMA_STREAM, \ - STM32_CRYP1_IN_DMA_MSK) -#error "invalid DMA stream associated to CRYP1_IN" -#endif - -#if STM32_CRY_USE_CRYP1 && \ - !STM32_DMA_IS_VALID_ID(STM32_CRY_CRYP1_OUT_DMA_STREAM, \ - STM32_CRYP1_OUT_DMA_MSK) -#error "invalid DMA stream associated to CRYP1_OUT" -#endif - -#if STM32_CRY_USE_HASH1 && \ - !STM32_DMA_IS_VALID_ID(STM32_CRY_HASH1_DMA_STREAM, STM32_HASH1_DMA_MSK) -#error "invalid DMA stream associated to HASH1" -#endif -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* DMA priority check.*/ -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_CRYP1_IN_DMA_PRIORITY) -#error "Invalid DMA priority assigned to CRYP1_IN" -#endif - -/* DMA priority check.*/ -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) -#error "Invalid DMA priority assigned to CRYP1_OUT" -#endif - -/* DMA priority check.*/ -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_HASH1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to HASH1" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -#if STM32_CRY_HASH_SIZE_THRESHOLD < 0 -#error "invalid STM32_CRY_HASH_SIZE_THRESHOLD value" -#endif - -/** - * @name Driver capability switches - * @{ - */ -#if STM32_CRY_USE_CRYP1 || defined (__DOXYGEN__) -#define CRY_LLD_SUPPORTS_AES TRUE -#define CRY_LLD_SUPPORTS_AES_ECB TRUE -#define CRY_LLD_SUPPORTS_AES_CBC TRUE -#define CRY_LLD_SUPPORTS_AES_CFB FALSE -#define CRY_LLD_SUPPORTS_AES_CTR TRUE -#define CRY_LLD_SUPPORTS_AES_GCM TRUE -#define CRY_LLD_SUPPORTS_DES TRUE -#define CRY_LLD_SUPPORTS_DES_ECB TRUE -#define CRY_LLD_SUPPORTS_DES_CBC TRUE -#else -#define CRY_LLD_SUPPORTS_AES FALSE -#define CRY_LLD_SUPPORTS_AES_ECB FALSE -#define CRY_LLD_SUPPORTS_AES_CBC FALSE -#define CRY_LLD_SUPPORTS_AES_CFB FALSE -#define CRY_LLD_SUPPORTS_AES_CTR FALSE -#define CRY_LLD_SUPPORTS_AES_GCM FALSE -#define CRY_LLD_SUPPORTS_DES FALSE -#define CRY_LLD_SUPPORTS_DES_ECB FALSE -#define CRY_LLD_SUPPORTS_DES_CBC FALSE -#endif -#if STM32_CRY_USE_HASH1 || defined (__DOXYGEN__) -#define CRY_LLD_SUPPORTS_SHA1 FALSE -#define CRY_LLD_SUPPORTS_SHA256 TRUE -#define CRY_LLD_SUPPORTS_SHA512 FALSE -#define CRY_LLD_SUPPORTS_HMAC_SHA256 TRUE -#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE -#else -#define CRY_LLD_SUPPORTS_SHA1 FALSE -#define CRY_LLD_SUPPORTS_SHA256 FALSE -#define CRY_LLD_SUPPORTS_SHA512 FALSE -#define CRY_LLD_SUPPORTS_HMAC_SHA256 FALSE -#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief CRY key identifier type. - */ -typedef uint32_t crykey_t; - -/** - * @brief Type of a structure representing an CRY driver. - */ -typedef struct CRYDriver CRYDriver; - -/** - * @brief Type of key stored in CRYP. - */ -typedef enum { - cryp_key_none = 0, - cryp_key_des = 1, - cryp_key_tdes = 2, - cryp_key_aes_encrypt = 3, - cryp_key_aes_decrypt = 4 -} cryp_ktype_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - uint32_t dummy; -} CRYConfig; - -/** - * @brief Structure representing an CRY driver. - */ -struct CRYDriver { - /** - * @brief Driver state. - */ - crystate_t state; - /** - * @brief Current configuration data. - */ - const CRYConfig *config; -#if defined(CRY_DRIVER_EXT_FIELDS) - CRY_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ -#if (STM32_CRY_USE_CRYP1 == TRUE) || defined (__DOXYGEN__) - /** - * @brief Type of the key currently stored in CRYP. - */ - cryp_ktype_t cryp_ktype; - /** - * @brief Key size setup value for CR register. - */ - uint32_t cryp_ksize; - /** - * @brief Transient key data. - */ - uint32_t cryp_k[8]; -#if (STM32_CRY_CRYP_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__) - /** - * @brief Thread reference for CRYP operations. - */ - thread_reference_t cryp_tr; - /** - * @brief CRYP IN DMA stream. - */ - const stm32_dma_stream_t *cryp_dma_in; - /** - * @brief CRYP OUT DMA stream. - */ - const stm32_dma_stream_t *cryp_dma_out; -#endif /* STM32_CRY_CRYP_SIZE_THRESHOLD != 0 */ -#endif /* STM32_CRY_USE_CRYP1 == TRUE */ -#if (STM32_CRY_USE_HASH1 == TRUE) || defined (__DOXYGEN__) -#if (STM32_CRY_HASH_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__) - /** - * @brief Thread reference for hash operations. - */ - thread_reference_t hash_tr; - /** - * @brief Hash DMA stream. - */ - const stm32_dma_stream_t *hash_dma; -#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */ -#endif /* STM32_CRY_USE_HASH1 == TRUE */ -}; - -#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a SHA1 context. - */ -typedef struct { - uint32_t dummy; -} SHA1Context; -#endif - -#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a SHA256 context. - */ -typedef struct { - /** - * @brief Last data to be hashed on finalization. - */ - uint32_t last_data; - /** - * @brief Size, in bits, of the last data. - */ - uint32_t last_size; -} SHA256Context; -#endif - -#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a SHA512 context. - */ -typedef struct { - uint32_t dummy; -} SHA512Context; -#endif - -#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a HMAC_SHA256 context. - */ -typedef struct { - uint32_t dummy; -} HMACSHA256Context; -#endif - -#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a HMAC_SHA512 context. - */ -typedef struct { - uint32_t dummy; -} HMACSHA512Context; -#endif - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if (STM32_CRY_ENABLED1 == TRUE) && !defined(__DOXYGEN__) -extern CRYDriver CRYD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void cry_lld_init(void); - void cry_lld_start(CRYDriver *cryp); - void cry_lld_stop(CRYDriver *cryp); -#if (CRY_LLD_SUPPORTS_AES == TRUE) || \ - (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || \ - (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || \ - (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || \ - (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || \ - (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || \ - defined(__DOXYGEN__) - cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp, - size_t size, - const uint8_t *keyp); -#endif -#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out); - cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out); - cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); - cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); -#endif -#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); - cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); -#endif -#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); - cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); -#endif -#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp, - crykey_t key_id, - size_t auth_size, - const uint8_t *auth_in, - size_t text_size, - const uint8_t *text_in, - uint8_t *text_out, - const uint8_t *iv, - size_t tag_size, - uint8_t *tag_out); - cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp, - crykey_t key_id, - size_t auth_size, - const uint8_t *auth_in, - size_t text_size, - const uint8_t *text_in, - uint8_t *text_out, - const uint8_t *iv, - size_t tag_size, - const uint8_t *tag_in); -#endif -#if (CRY_LLD_SUPPORTS_DES == TRUE) || \ - (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || \ - (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || \ - defined(__DOXYGEN__) - cryerror_t cry_lld_des_loadkey(CRYDriver *cryp, - size_t size, - const uint8_t *keyp); -#endif -#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out); - cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp, - crykey_t key_id, - const uint8_t *in, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out); - cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); - cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp, - crykey_t key_id, - size_t size, - const uint8_t *in, - uint8_t *out, - const uint8_t *iv); -#endif -#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp); - cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp, - size_t size, const uint8_t *in); - cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp); - cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp, - size_t size, const uint8_t *in); - cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp); - cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp, - size_t size, const uint8_t *in); - cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || \ - (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || \ - defined(__DOXYGEN__) - cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp, - size_t size, - const uint8_t *keyp); -#endif -#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp, - HMACSHA256Context *hmacsha256ctxp); - cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp, - HMACSHA256Context *hmacsha256ctxp, - size_t size, const uint8_t *in); - cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp, - HMACSHA256Context *hmacsha256ctxp, - uint8_t *out); -#endif -#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__) - cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp, - HMACSHA512Context *hmacsha512ctxp); - cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp, - HMACSHA512Context *hmacsha512ctxp, - size_t size, const uint8_t *in); - cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp, - HMACSHA512Context *hmacsha512ctxp, - uint8_t *out); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_CRY == TRUE */ - -#endif /* HAL_CRYPTO_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file CRYPv1/hal_cry_lld.h + * @brief STM32 cryptographic subsystem low level driver header. + * + * @addtogroup CRYPTO + * @{ + */ + +#ifndef HAL_CRYPTO_LLD_H +#define HAL_CRYPTO_LLD_H + +#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name STM32 configuration options + * @{ + */ +/** + * @brief CRYP1 driver enable switch. + * @details If set to @p TRUE the support for CRYP1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_CRY_USE_CRYP1) || defined(__DOXYGEN__) +#define STM32_CRY_USE_CRYP1 FALSE +#endif + +/** + * @brief HASH1 driver enable switch. + * @details If set to @p TRUE the support for HASH1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_CRY_USE_HASH1) || defined(__DOXYGEN__) +#define STM32_CRY_USE_HASH1 FALSE +#endif + +/** + * @brief CRYP1 interrupt priority level setting. + */ +#if !defined(STM32_CRY_CRYP1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CRY_CRYP1_IRQ_PRIORITY 9 +#endif + +/** + * @brief HASH1 interrupt priority level setting. + */ +#if !defined(STM32_CRY_HASH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CRY_HASH1_IRQ_PRIORITY 9 +#endif + +/** + * @brief HASH1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CRY_CRYP1_OUT_DMA_PRIORITY 0 +#endif + +/** + * @brief HASH1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_CRY_HASH1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CRY_HASH1_DMA_PRIORITY 0 +#endif + +/** + * @brief Minimum message size (in words) for DMA use. + * @note If set to zero then DMA is never used. + * @note If set to one then DMA is always used. + */ +#if !defined(STM32_CRY_HASH_SIZE_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_CRY_HASH_SIZE_THRESHOLD 1024 +#endif + +/** + * @brief Minimum text size (in bytes) for DMA use. + * @note If set to zero then DMA is never used. + * @note If set to one then DMA is always used. + */ +#if !defined(STM32_CRY_CRYP_SIZE_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_CRY_CRYP_SIZE_THRESHOLD 1024 +#endif + +/** + * @brief Hash DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_CRY_HASH_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_CRY_HASH_DMA_ERROR_HOOK(cryp) osalSysHalt("DMA failure") +#endif + +/** + * @brief CRYP DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if (STM32_CRY_USE_CRYP1 == TRUE) || (STM32_CRY_USE_HASH1 == TRUE) || \ + defined (__DOXYGEN__) +#define STM32_CRY_ENABLED1 TRUE +#else +#define STM32_CRY_ENABLED1 FALSE +#endif + +#if !defined (STM32_HAS_CRYP1) +#define STM32_HAS_CRYP1 FALSE +#endif + +#if !defined (STM32_HAS_HASH1) +#define STM32_HAS_HASH1 FALSE +#endif + +#if STM32_CRY_USE_CRYP1 && !STM32_HAS_CRYP1 +#error "CRYP1 not present in the selected device" +#endif + +#if STM32_CRY_USE_HASH1 && !STM32_HAS_HASH1 +#error "HASH1 not present in the selected device" +#endif + +#if !STM32_CRY_ENABLED1 +#error "CRY driver activated but no CRYP nor HASH peripheral assigned" +#endif + +#if STM32_CRY_USE_HASH1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_CRY_HASH1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to HASH1" +#endif + +#if STM32_CRY_USE_CRYP1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_CRY_CRYP1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to CRYP1" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if !defined(STM32_CRY_HASH1_DMA_STREAM) +#error "HASH1 DMA streams not defined" +#endif + +/* Sanity checks on DMA streams settings in mcuconf.h.*/ +#if STM32_CRY_USE_HASH1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_CRY_HASH1_DMA_STREAM) +#error "Invalid DMA stream assigned to HASH1" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if !STM32_DMA_SUPPORTS_DMAMUX +#if STM32_CRY_USE_CRYP1 && \ + !STM32_DMA_IS_VALID_ID(STM32_CRY_CRYP1_IN_DMA_STREAM, \ + STM32_CRYP1_IN_DMA_MSK) +#error "invalid DMA stream associated to CRYP1_IN" +#endif + +#if STM32_CRY_USE_CRYP1 && \ + !STM32_DMA_IS_VALID_ID(STM32_CRY_CRYP1_OUT_DMA_STREAM, \ + STM32_CRYP1_OUT_DMA_MSK) +#error "invalid DMA stream associated to CRYP1_OUT" +#endif + +#if STM32_CRY_USE_HASH1 && \ + !STM32_DMA_IS_VALID_ID(STM32_CRY_HASH1_DMA_STREAM, STM32_HASH1_DMA_MSK) +#error "invalid DMA stream associated to HASH1" +#endif +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* DMA priority check.*/ +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_CRYP1_IN_DMA_PRIORITY) +#error "Invalid DMA priority assigned to CRYP1_IN" +#endif + +/* DMA priority check.*/ +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) +#error "Invalid DMA priority assigned to CRYP1_OUT" +#endif + +/* DMA priority check.*/ +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_HASH1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to HASH1" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +#if STM32_CRY_HASH_SIZE_THRESHOLD < 0 +#error "invalid STM32_CRY_HASH_SIZE_THRESHOLD value" +#endif + +/** + * @name Driver capability switches + * @{ + */ +#if STM32_CRY_USE_CRYP1 || defined (__DOXYGEN__) +#define CRY_LLD_SUPPORTS_AES TRUE +#define CRY_LLD_SUPPORTS_AES_ECB TRUE +#define CRY_LLD_SUPPORTS_AES_CBC TRUE +#define CRY_LLD_SUPPORTS_AES_CFB FALSE +#define CRY_LLD_SUPPORTS_AES_CTR TRUE +#define CRY_LLD_SUPPORTS_AES_GCM TRUE +#define CRY_LLD_SUPPORTS_DES TRUE +#define CRY_LLD_SUPPORTS_DES_ECB TRUE +#define CRY_LLD_SUPPORTS_DES_CBC TRUE +#else +#define CRY_LLD_SUPPORTS_AES FALSE +#define CRY_LLD_SUPPORTS_AES_ECB FALSE +#define CRY_LLD_SUPPORTS_AES_CBC FALSE +#define CRY_LLD_SUPPORTS_AES_CFB FALSE +#define CRY_LLD_SUPPORTS_AES_CTR FALSE +#define CRY_LLD_SUPPORTS_AES_GCM FALSE +#define CRY_LLD_SUPPORTS_DES FALSE +#define CRY_LLD_SUPPORTS_DES_ECB FALSE +#define CRY_LLD_SUPPORTS_DES_CBC FALSE +#endif +#if STM32_CRY_USE_HASH1 || defined (__DOXYGEN__) +#define CRY_LLD_SUPPORTS_SHA1 FALSE +#define CRY_LLD_SUPPORTS_SHA256 TRUE +#define CRY_LLD_SUPPORTS_SHA512 FALSE +#define CRY_LLD_SUPPORTS_HMAC_SHA256 TRUE +#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE +#else +#define CRY_LLD_SUPPORTS_SHA1 FALSE +#define CRY_LLD_SUPPORTS_SHA256 FALSE +#define CRY_LLD_SUPPORTS_SHA512 FALSE +#define CRY_LLD_SUPPORTS_HMAC_SHA256 FALSE +#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief CRY key identifier type. + */ +typedef uint32_t crykey_t; + +/** + * @brief Type of a structure representing an CRY driver. + */ +typedef struct CRYDriver CRYDriver; + +/** + * @brief Type of key stored in CRYP. + */ +typedef enum { + cryp_key_none = 0, + cryp_key_des = 1, + cryp_key_tdes = 2, + cryp_key_aes_encrypt = 3, + cryp_key_aes_decrypt = 4 +} cryp_ktype_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + uint32_t dummy; +} CRYConfig; + +/** + * @brief Structure representing an CRY driver. + */ +struct CRYDriver { + /** + * @brief Driver state. + */ + crystate_t state; + /** + * @brief Current configuration data. + */ + const CRYConfig *config; +#if defined(CRY_DRIVER_EXT_FIELDS) + CRY_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ +#if (STM32_CRY_USE_CRYP1 == TRUE) || defined (__DOXYGEN__) + /** + * @brief Type of the key currently stored in CRYP. + */ + cryp_ktype_t cryp_ktype; + /** + * @brief Key size setup value for CR register. + */ + uint32_t cryp_ksize; + /** + * @brief Transient key data. + */ + uint32_t cryp_k[8]; +#if (STM32_CRY_CRYP_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__) + /** + * @brief Thread reference for CRYP operations. + */ + thread_reference_t cryp_tr; + /** + * @brief CRYP IN DMA stream. + */ + const stm32_dma_stream_t *cryp_dma_in; + /** + * @brief CRYP OUT DMA stream. + */ + const stm32_dma_stream_t *cryp_dma_out; +#endif /* STM32_CRY_CRYP_SIZE_THRESHOLD != 0 */ +#endif /* STM32_CRY_USE_CRYP1 == TRUE */ +#if (STM32_CRY_USE_HASH1 == TRUE) || defined (__DOXYGEN__) +#if (STM32_CRY_HASH_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__) + /** + * @brief Thread reference for hash operations. + */ + thread_reference_t hash_tr; + /** + * @brief Hash DMA stream. + */ + const stm32_dma_stream_t *hash_dma; +#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */ +#endif /* STM32_CRY_USE_HASH1 == TRUE */ +}; + +#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a SHA1 context. + */ +typedef struct { + uint32_t dummy; +} SHA1Context; +#endif + +#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a SHA256 context. + */ +typedef struct { + /** + * @brief Last data to be hashed on finalization. + */ + uint32_t last_data; + /** + * @brief Size, in bits, of the last data. + */ + uint32_t last_size; +} SHA256Context; +#endif + +#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a SHA512 context. + */ +typedef struct { + uint32_t dummy; +} SHA512Context; +#endif + +#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a HMAC_SHA256 context. + */ +typedef struct { + uint32_t dummy; +} HMACSHA256Context; +#endif + +#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a HMAC_SHA512 context. + */ +typedef struct { + uint32_t dummy; +} HMACSHA512Context; +#endif + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (STM32_CRY_ENABLED1 == TRUE) && !defined(__DOXYGEN__) +extern CRYDriver CRYD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void cry_lld_init(void); + void cry_lld_start(CRYDriver *cryp); + void cry_lld_stop(CRYDriver *cryp); +#if (CRY_LLD_SUPPORTS_AES == TRUE) || \ + (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || \ + (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || \ + (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || \ + (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || \ + (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || \ + defined(__DOXYGEN__) + cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp, + size_t size, + const uint8_t *keyp); +#endif +#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out); + cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out); + cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); + cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); +#endif +#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); + cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); +#endif +#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); + cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); +#endif +#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp, + crykey_t key_id, + size_t auth_size, + const uint8_t *auth_in, + size_t text_size, + const uint8_t *text_in, + uint8_t *text_out, + const uint8_t *iv, + size_t tag_size, + uint8_t *tag_out); + cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp, + crykey_t key_id, + size_t auth_size, + const uint8_t *auth_in, + size_t text_size, + const uint8_t *text_in, + uint8_t *text_out, + const uint8_t *iv, + size_t tag_size, + const uint8_t *tag_in); +#endif +#if (CRY_LLD_SUPPORTS_DES == TRUE) || \ + (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || \ + (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || \ + defined(__DOXYGEN__) + cryerror_t cry_lld_des_loadkey(CRYDriver *cryp, + size_t size, + const uint8_t *keyp); +#endif +#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out); + cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp, + crykey_t key_id, + const uint8_t *in, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out); + cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); + cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp, + crykey_t key_id, + size_t size, + const uint8_t *in, + uint8_t *out, + const uint8_t *iv); +#endif +#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp); + cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp, + size_t size, const uint8_t *in); + cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp); + cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp, + size_t size, const uint8_t *in); + cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp); + cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp, + size_t size, const uint8_t *in); + cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || \ + (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || \ + defined(__DOXYGEN__) + cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp, + size_t size, + const uint8_t *keyp); +#endif +#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp, + HMACSHA256Context *hmacsha256ctxp); + cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp, + HMACSHA256Context *hmacsha256ctxp, + size_t size, const uint8_t *in); + cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp, + HMACSHA256Context *hmacsha256ctxp, + uint8_t *out); +#endif +#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__) + cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp, + HMACSHA512Context *hmacsha512ctxp); + cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp, + HMACSHA512Context *hmacsha512ctxp, + size_t size, const uint8_t *in); + cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp, + HMACSHA512Context *hmacsha512ctxp, + uint8_t *out); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_CRY == TRUE */ + +#endif /* HAL_CRYPTO_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/DACv1/driver.mk b/os/hal/ports/STM32/LLD/DACv1/driver.mk index da951486d6..7807214bac 100644 --- a/os/hal/ports/STM32/LLD/DACv1/driver.mk +++ b/os/hal/ports/STM32/LLD/DACv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_DAC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_DAC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1 diff --git a/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c b/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c index ca6ebf90cf..a5e6e14766 100644 --- a/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c +++ b/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c @@ -1,785 +1,785 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file DACv1/hal_dac_lld.c - * @brief STM32 DAC subsystem low level driver source. - * - * @addtogroup DAC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_DAC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* Because ST headers naming inconsistencies.*/ -#if !defined(DAC1) -#define DAC1 DAC -#endif - -#define DAC1_CH1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC1_CH1_DMA_STREAM, \ - STM32_DAC1_CH1_DMA_CHN) - -#define DAC1_CH2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC1_CH2_DMA_STREAM, \ - STM32_DAC1_CH2_DMA_CHN) - -#define DAC2_CH1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC2_CH1_DMA_STREAM, \ - STM32_DAC2_CH1_DMA_CHN) - -#define DAC2_CH2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC2_CH2_DMA_STREAM, \ - STM32_DAC2_CH2_DMA_CHN) - -#define DAC3_CH1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC3_CH1_DMA_STREAM, \ - STM32_DAC3_CH1_DMA_CHN) - -#define DAC3_CH2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC3_CH2_DMA_STREAM, \ - STM32_DAC3_CH2_DMA_CHN) - -#define DAC4_CH1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC4_CH1_DMA_STREAM, \ - STM32_DAC4_CH1_DMA_CHN) - -#define DAC4_CH2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_DAC_DAC4_CH2_DMA_STREAM, \ - STM32_DAC4_CH2_DMA_CHN) - -#define CHANNEL_DATA_OFFSET 3U - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief DAC1 CH1 driver identifier.*/ -#if STM32_DAC_USE_DAC1_CH1 || defined(__DOXYGEN__) -DACDriver DACD1; -#endif - -/** @brief DAC1 CH2 driver identifier.*/ -#if (STM32_DAC_USE_DAC1_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) -DACDriver DACD2; -#endif - -/** @brief DAC2 CH1 driver identifier.*/ -#if STM32_DAC_USE_DAC2_CH1 || defined(__DOXYGEN__) -DACDriver DACD3; -#endif - -/** @brief DAC2 CH2 driver identifier.*/ -#if (STM32_DAC_USE_DAC2_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) -DACDriver DACD4; -#endif - -/** @brief DAC3 CH1 driver identifier.*/ -#if STM32_DAC_USE_DAC3_CH1 || defined(__DOXYGEN__) -DACDriver DACD5; -#endif - -/** @brief DAC3 CH2 driver identifier.*/ -#if (STM32_DAC_USE_DAC3_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) -DACDriver DACD6; -#endif - -/** @brief DAC4 CH1 driver identifier.*/ -#if STM32_DAC_USE_DAC4_CH1 || defined(__DOXYGEN__) -DACDriver DACD7; -#endif - -/** @brief DAC4 CH2 driver identifier.*/ -#if (STM32_DAC_USE_DAC4_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) -DACDriver DACD8; -#endif - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -#if STM32_DAC_USE_DAC1_CH1 == TRUE -static const dacparams_t dac1_ch1_params = { - .dac = DAC1, - .dataoffset = 0U, - .regshift = 0U, - .regmask = 0xFFFF0000U, - .dmastream = STM32_DAC_DAC1_CH1_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC1_CH1, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC1_CH1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC1_CH1_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC1_CH1_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC1_CH2 == TRUE -static const dacparams_t dac1_ch2_params = { - .dac = DAC1, - .dataoffset = CHANNEL_DATA_OFFSET, - .regshift = 16U, - .regmask = 0x0000FFFFU, - .dmastream = STM32_DAC_DAC1_CH2_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC1_CH2, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC1_CH2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC1_CH2_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC1_CH2_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC2_CH1 == TRUE -static const dacparams_t dac2_ch1_params = { - .dac = DAC2, - .dataoffset = 0U, - .regshift = 0U, - .regmask = 0xFFFF0000U, - .dmastream = STM32_DAC_DAC2_CH1_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC2_CH1, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC2_CH1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC2_CH1_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC2_CH1_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC2_CH2 == TRUE -static const dacparams_t dac2_ch2_params = { - .dac = DAC2, - .dataoffset = CHANNEL_DATA_OFFSET, - .regshift = 16U, - .regmask = 0x0000FFFFU, - .dmastream = STM32_DAC_DAC2_CH2_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC2_CH2, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC2_CH2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC2_CH2_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC2_CH2_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC3_CH1 == TRUE -static const dacparams_t dac3_ch1_params = { - .dac = DAC3, - .dataoffset = 0U, - .regshift = 0U, - .regmask = 0xFFFF0000U, - .dmastream = STM32_DAC_DAC3_CH1_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC3_CH1, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC3_CH1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC3_CH1_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC3_CH1_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC3_CH2 == TRUE -static const dacparams_t dac3_ch2_params = { - .dac = DAC3, - .dataoffset = CHANNEL_DATA_OFFSET, - .regshift = 16U, - .regmask = 0x0000FFFFU, - .dmastream = STM32_DAC_DAC3_CH2_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC3_CH2, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC3_CH2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC3_CH2_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC3_CH2_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC4_CH1 == TRUE -static const dacparams_t dac4_ch1_params = { - .dac = DAC4, - .dataoffset = 0U, - .regshift = 0U, - .regmask = 0xFFFF0000U, - .dmastream = STM32_DAC_DAC4_CH1_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC4_CH1, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC4_CH1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC4_CH1_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC4_CH1_IRQ_PRIORITY -}; -#endif - -#if STM32_DAC_USE_DAC4_CH2 == TRUE -static const dacparams_t dac4_ch2_params = { - .dac = DAC4, - .dataoffset = CHANNEL_DATA_OFFSET, - .regshift = 16U, - .regmask = 0x0000FFFFU, - .dmastream = STM32_DAC_DAC4_CH2_DMA_STREAM, -#if STM32_DMA_SUPPORTS_DMAMUX - .peripheral = STM32_DMAMUX1_DAC4_CH2, -#endif - .dmamode = STM32_DMA_CR_CHSEL(DAC4_CH2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_DAC_DAC4_CH2_DMA_PRIORITY) | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE, - .dmairqprio = STM32_DAC_DAC4_CH2_IRQ_PRIORITY -}; -#endif - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared end/half-of-tx service routine. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void dac_lld_serve_tx_interrupt(DACDriver *dacp, uint32_t flags) { - - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA errors handling.*/ - dac_lld_stop_conversion(dacp); - _dac_isr_error_code(dacp, DAC_ERR_DMAFAILURE); - } - else { - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _dac_isr_half_code(dacp); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _dac_isr_full_code(dacp); - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level DAC driver initialization. - * - * @notapi - */ -void dac_lld_init(void) { - -#if STM32_DAC_USE_DAC1_CH1 - dacObjectInit(&DACD1); - DACD1.params = &dac1_ch1_params; - DACD1.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC1_CH2 - dacObjectInit(&DACD2); - DACD2.params = &dac1_ch2_params; - DACD2.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC2_CH1 - dacObjectInit(&DACD3); - DACD3.params = &dac2_ch1_params; - DACD3.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC2_CH2 - dacObjectInit(&DACD4); - DACD4.params = &dac2_ch2_params; - DACD4.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC3_CH1 - dacObjectInit(&DACD5); - DACD5.params = &dac3_ch1_params; - DACD5.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC3_CH2 - dacObjectInit(&DACD6); - DACD6.params = &dac3_ch2_params; - DACD6.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC4_CH1 - dacObjectInit(&DACD7); - DACD7.params = &dac4_ch1_params; - DACD7.dma = NULL; -#endif - -#if STM32_DAC_USE_DAC4_CH2 - dacObjectInit(&DACD8); - DACD8.params = &dac4_ch2_params; - DACD8.dma = NULL; -#endif -} - -/** - * @brief Configures and activates the DAC peripheral. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -void dac_lld_start(DACDriver *dacp) { - - /* If the driver is in DAC_STOP state then a full initialization is - required.*/ - if (dacp->state == DAC_STOP) { - dacchannel_t channel = 0; - - /* Enabling the clock source.*/ -#if STM32_DAC_USE_DAC1_CH1 - if (&DACD1 == dacp) { - rccEnableDAC1(true); - } -#endif - -#if STM32_DAC_USE_DAC1_CH2 - if (&DACD2 == dacp) { - rccEnableDAC1(true); - channel = 1; - } -#endif - -#if STM32_DAC_USE_DAC2_CH1 - if (&DACD3 == dacp) { - rccEnableDAC2(true); - } -#endif - -#if STM32_DAC_USE_DAC2_CH2 - if (&DACD4 == dacp) { - rccEnableDAC2(true); - channel = 1; - } -#endif - -#if STM32_DAC_USE_DAC3_CH1 - if (&DACD5 == dacp) { - rccEnableDAC3(true); - } -#endif - -#if STM32_DAC_USE_DAC3_CH2 - if (&DACD6 == dacp) { - rccEnableDAC3(true); - channel = 1; - } -#endif - -#if STM32_DAC_USE_DAC4_CH1 - if (&DACD7 == dacp) { - rccEnableDAC4(true); - } -#endif - -#if STM32_DAC_USE_DAC4_CH2 - if (&DACD8 == dacp) { - rccEnableDAC4(true); - channel = 1; - } -#endif - - /* Enabling DAC in SW triggering mode initially, initializing data to - zero.*/ -#if STM32_DAC_DUAL_MODE == FALSE - { - uint32_t cr; - - cr = dacp->params->dac->CR; - cr &= dacp->params->regmask; - cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift; - dacp->params->dac->CR = cr; - dac_lld_put_channel(dacp, channel, dacp->config->init); - } -#else - if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) || - (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) || - (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) { - dacp->params->dac->CR = DAC_CR_EN2 | (dacp->config->cr << 16) | DAC_CR_EN1 | dacp->config->cr; - dac_lld_put_channel(dacp, 1U, dacp->config->init); - } - else { - dacp->params->dac->CR = DAC_CR_EN1 | dacp->config->cr; - } - dac_lld_put_channel(dacp, channel, dacp->config->init); -#endif - } -} - -/** - * @brief Deactivates the DAC peripheral. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -void dac_lld_stop(DACDriver *dacp) { - - /* If in ready state then disables the DAC clock.*/ - if (dacp->state == DAC_READY) { - - /* Disabling DAC.*/ - dacp->params->dac->CR &= dacp->params->regmask; - -#if STM32_DAC_USE_DAC1_CH1 - if (&DACD1 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { - rccDisableDAC1(); - } - } -#endif - -#if STM32_DAC_USE_DAC1_CH2 - if (&DACD2 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { - rccDisableDAC1(); - } - } -#endif - -#if STM32_DAC_USE_DAC2_CH1 - if (&DACD3 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { - rccDisableDAC2(); - } - } -#endif - -#if STM32_DAC_USE_DAC2_CH2 - if (&DACD4 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { - rccDisableDAC2(); - } - } -#endif - -#if STM32_DAC_USE_DAC3_CH1 - if (&DACD5 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { - rccDisableDAC3(); - } - } -#endif - -#if STM32_DAC_USE_DAC3_CH2 - if (&DACD6 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { - rccDisableDAC3(); - } - } -#endif - -#if STM32_DAC_USE_DAC4_CH1 - if (&DACD7 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { - rccDisableDAC4(); - } - } -#endif - -#if STM32_DAC_USE_DAC4_CH2 - if (&DACD8 == dacp) { - if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { - rccDisableDAC4(); - } - } -#endif - } -} - -/** - * @brief Outputs a value directly on a DAC channel. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] channel DAC channel number - * @param[in] sample value to be output - * - * @api - */ -void dac_lld_put_channel(DACDriver *dacp, - dacchannel_t channel, - dacsample_t sample) { - - switch (dacp->config->datamode) { - case DAC_DHRM_12BIT_RIGHT: -#if STM32_DAC_DUAL_MODE - case DAC_DHRM_12BIT_RIGHT_DUAL: -#endif - if (channel == 0U) { -#if STM32_DAC_DUAL_MODE - dacp->params->dac->DHR12R1 = (uint32_t)sample; -#else - *(&dacp->params->dac->DHR12R1 + dacp->params->dataoffset) = (uint32_t)sample; -#endif - } -#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \ - STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2) - else { - dacp->params->dac->DHR12R2 = (uint32_t)sample; - } -#endif - break; - case DAC_DHRM_12BIT_LEFT: -#if STM32_DAC_DUAL_MODE - case DAC_DHRM_12BIT_LEFT_DUAL: -#endif - if (channel == 0U) { -#if STM32_DAC_DUAL_MODE - dacp->params->dac->DHR12L1 = (uint32_t)sample; -#else - *(&dacp->params->dac->DHR12L1 + dacp->params->dataoffset) = (uint32_t)sample; -#endif - } -#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \ - STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2) - else { - dacp->params->dac->DHR12L2 = (uint32_t)sample; - } -#endif - break; - case DAC_DHRM_8BIT_RIGHT: -#if STM32_DAC_DUAL_MODE - case DAC_DHRM_8BIT_RIGHT_DUAL: -#endif - if (channel == 0U) { -#if STM32_DAC_DUAL_MODE - dacp->params->dac->DHR8R1 = (uint32_t)sample; -#else - *(&dacp->params->dac->DHR8R1 + dacp->params->dataoffset) = (uint32_t)sample; -#endif - } -#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \ - STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2) - else { - dacp->params->dac->DHR8R2 = (uint32_t)sample; - } -#endif - break; - default: - osalDbgAssert(false, "unexpected DAC mode"); - break; - } -} - -/** - * @brief Starts a DAC conversion. - * @details Starts an asynchronous conversion operation. - * @note In @p DAC_DHRM_8BIT_RIGHT mode the parameters passed to the - * callback are wrong because two samples are packed in a single - * dacsample_t element. This will not be corrected, do not rely - * on those parameters. - * @note In @p DAC_DHRM_8BIT_RIGHT_DUAL mode two samples are treated - * as a single 16 bits sample and packed into a single dacsample_t - * element. The num_channels must be set to one in the group - * conversion configuration structure. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -void dac_lld_start_conversion(DACDriver *dacp) { - uint32_t n, cr, dmamode; - - /* Number of DMA operations per buffer.*/ - n = dacp->depth * dacp->grpp->num_channels; - - /* Allocating the DMA channel.*/ - dacp->dma = dmaStreamAllocI(dacp->params->dmastream, - dacp->params->dmairqprio, - (stm32_dmaisr_t)dac_lld_serve_tx_interrupt, - (void *)dacp); - osalDbgAssert(dacp->dma != NULL, "unable to allocate stream"); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(dacp->dma, dacp->params->peripheral); -#endif - - /* DMA settings depend on the chosen DAC mode.*/ - switch (dacp->config->datamode) { - /* Sets the DAC data register */ - case DAC_DHRM_12BIT_RIGHT: - osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); - - dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12R1 + - dacp->params->dataoffset); - dmamode = dacp->params->dmamode | -#if STM32_DMA_ADVANCED == FALSE - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_HWORD; -#else - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; -#endif - break; - case DAC_DHRM_12BIT_LEFT: - osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); - - dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12L1 + - dacp->params->dataoffset); - dmamode = dacp->params->dmamode | -#if STM32_DMA_ADVANCED == FALSE - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_HWORD; -#else - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; -#endif - break; - case DAC_DHRM_8BIT_RIGHT: - osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); - - dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR8R1 + - dacp->params->dataoffset); - dmamode = dacp->params->dmamode | -#if STM32_DMA_ADVANCED == FALSE - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_BYTE; -#else - STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; -#endif - - /* In this mode the size of the buffer is halved because two samples - packed in a single dacsample_t element.*/ - n = (n + 1) / 2; - break; -#if STM32_DAC_DUAL_MODE == TRUE - case DAC_DHRM_12BIT_RIGHT_DUAL: - osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels"); - - dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12RD); - dmamode = dacp->params->dmamode | - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; - n /= 2; - break; - case DAC_DHRM_12BIT_LEFT_DUAL: - osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels"); - - dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12LD); - dmamode = dacp->params->dmamode | - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; - n /= 2; - break; - case DAC_DHRM_8BIT_RIGHT_DUAL: - osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); - - dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR8RD); - dmamode = dacp->params->dmamode | -#if STM32_DMA_ADVANCED == FALSE - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_HWORD; -#else - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; -#endif - n /= 2; - break; -#endif - default: - osalDbgAssert(false, "unexpected DAC mode"); - return; - } - - dmaStreamSetMemory0(dacp->dma, dacp->samples); - dmaStreamSetTransactionSize(dacp->dma, n); - dmaStreamSetMode(dacp->dma, dmamode | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | - STM32_DMA_CR_HTIE | STM32_DMA_CR_TCIE); - dmaStreamEnable(dacp->dma); - - /* DAC configuration.*/ - cr = dacp->params->dac->CR; - -#if STM32_DAC_DUAL_MODE == FALSE - cr &= dacp->params->regmask; - cr |= (DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift; -#else - cr = DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr - | (dacp->grpp->trigger << DAC_CR_TSEL2_Pos) | DAC_CR_TEN2 | DAC_CR_EN2 | (dacp->config->cr << 16); -#endif - - dacp->params->dac->CR = cr; -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p DAC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @iclass - */ -void dac_lld_stop_conversion(DACDriver *dacp) { - uint32_t cr; - - /* DMA channel disabled and released.*/ - dmaStreamDisable(dacp->dma); - dmaStreamFreeI(dacp->dma); - dacp->dma = NULL; - - cr = dacp->params->dac->CR; - -#if STM32_DAC_DUAL_MODE == FALSE - cr &= dacp->params->regmask; - cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift; -#else - if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) || - (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) || - (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) { - cr = DAC_CR_EN2 | (dacp->config->cr << 16) | - DAC_CR_EN1 | dacp->config->cr; - } - else { - cr = DAC_CR_EN1 | dacp->config->cr; - } -#endif - - dacp->params->dac->CR = cr; -} - -#endif /* HAL_USE_DAC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file DACv1/hal_dac_lld.c + * @brief STM32 DAC subsystem low level driver source. + * + * @addtogroup DAC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_DAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* Because ST headers naming inconsistencies.*/ +#if !defined(DAC1) +#define DAC1 DAC +#endif + +#define DAC1_CH1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC1_CH1_DMA_STREAM, \ + STM32_DAC1_CH1_DMA_CHN) + +#define DAC1_CH2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC1_CH2_DMA_STREAM, \ + STM32_DAC1_CH2_DMA_CHN) + +#define DAC2_CH1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC2_CH1_DMA_STREAM, \ + STM32_DAC2_CH1_DMA_CHN) + +#define DAC2_CH2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC2_CH2_DMA_STREAM, \ + STM32_DAC2_CH2_DMA_CHN) + +#define DAC3_CH1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC3_CH1_DMA_STREAM, \ + STM32_DAC3_CH1_DMA_CHN) + +#define DAC3_CH2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC3_CH2_DMA_STREAM, \ + STM32_DAC3_CH2_DMA_CHN) + +#define DAC4_CH1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC4_CH1_DMA_STREAM, \ + STM32_DAC4_CH1_DMA_CHN) + +#define DAC4_CH2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_DAC_DAC4_CH2_DMA_STREAM, \ + STM32_DAC4_CH2_DMA_CHN) + +#define CHANNEL_DATA_OFFSET 3U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief DAC1 CH1 driver identifier.*/ +#if STM32_DAC_USE_DAC1_CH1 || defined(__DOXYGEN__) +DACDriver DACD1; +#endif + +/** @brief DAC1 CH2 driver identifier.*/ +#if (STM32_DAC_USE_DAC1_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) +DACDriver DACD2; +#endif + +/** @brief DAC2 CH1 driver identifier.*/ +#if STM32_DAC_USE_DAC2_CH1 || defined(__DOXYGEN__) +DACDriver DACD3; +#endif + +/** @brief DAC2 CH2 driver identifier.*/ +#if (STM32_DAC_USE_DAC2_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) +DACDriver DACD4; +#endif + +/** @brief DAC3 CH1 driver identifier.*/ +#if STM32_DAC_USE_DAC3_CH1 || defined(__DOXYGEN__) +DACDriver DACD5; +#endif + +/** @brief DAC3 CH2 driver identifier.*/ +#if (STM32_DAC_USE_DAC3_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) +DACDriver DACD6; +#endif + +/** @brief DAC4 CH1 driver identifier.*/ +#if STM32_DAC_USE_DAC4_CH1 || defined(__DOXYGEN__) +DACDriver DACD7; +#endif + +/** @brief DAC4 CH2 driver identifier.*/ +#if (STM32_DAC_USE_DAC4_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) +DACDriver DACD8; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +#if STM32_DAC_USE_DAC1_CH1 == TRUE +static const dacparams_t dac1_ch1_params = { + .dac = DAC1, + .dataoffset = 0U, + .regshift = 0U, + .regmask = 0xFFFF0000U, + .dmastream = STM32_DAC_DAC1_CH1_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC1_CH1, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC1_CH1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC1_CH1_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC1_CH1_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC1_CH2 == TRUE +static const dacparams_t dac1_ch2_params = { + .dac = DAC1, + .dataoffset = CHANNEL_DATA_OFFSET, + .regshift = 16U, + .regmask = 0x0000FFFFU, + .dmastream = STM32_DAC_DAC1_CH2_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC1_CH2, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC1_CH2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC1_CH2_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC1_CH2_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC2_CH1 == TRUE +static const dacparams_t dac2_ch1_params = { + .dac = DAC2, + .dataoffset = 0U, + .regshift = 0U, + .regmask = 0xFFFF0000U, + .dmastream = STM32_DAC_DAC2_CH1_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC2_CH1, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC2_CH1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC2_CH1_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC2_CH1_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC2_CH2 == TRUE +static const dacparams_t dac2_ch2_params = { + .dac = DAC2, + .dataoffset = CHANNEL_DATA_OFFSET, + .regshift = 16U, + .regmask = 0x0000FFFFU, + .dmastream = STM32_DAC_DAC2_CH2_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC2_CH2, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC2_CH2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC2_CH2_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC2_CH2_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC3_CH1 == TRUE +static const dacparams_t dac3_ch1_params = { + .dac = DAC3, + .dataoffset = 0U, + .regshift = 0U, + .regmask = 0xFFFF0000U, + .dmastream = STM32_DAC_DAC3_CH1_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC3_CH1, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC3_CH1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC3_CH1_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC3_CH1_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC3_CH2 == TRUE +static const dacparams_t dac3_ch2_params = { + .dac = DAC3, + .dataoffset = CHANNEL_DATA_OFFSET, + .regshift = 16U, + .regmask = 0x0000FFFFU, + .dmastream = STM32_DAC_DAC3_CH2_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC3_CH2, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC3_CH2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC3_CH2_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC3_CH2_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC4_CH1 == TRUE +static const dacparams_t dac4_ch1_params = { + .dac = DAC4, + .dataoffset = 0U, + .regshift = 0U, + .regmask = 0xFFFF0000U, + .dmastream = STM32_DAC_DAC4_CH1_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC4_CH1, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC4_CH1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC4_CH1_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC4_CH1_IRQ_PRIORITY +}; +#endif + +#if STM32_DAC_USE_DAC4_CH2 == TRUE +static const dacparams_t dac4_ch2_params = { + .dac = DAC4, + .dataoffset = CHANNEL_DATA_OFFSET, + .regshift = 16U, + .regmask = 0x0000FFFFU, + .dmastream = STM32_DAC_DAC4_CH2_DMA_STREAM, +#if STM32_DMA_SUPPORTS_DMAMUX + .peripheral = STM32_DMAMUX1_DAC4_CH2, +#endif + .dmamode = STM32_DMA_CR_CHSEL(DAC4_CH2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_DAC_DAC4_CH2_DMA_PRIORITY) | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE, + .dmairqprio = STM32_DAC_DAC4_CH2_IRQ_PRIORITY +}; +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared end/half-of-tx service routine. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void dac_lld_serve_tx_interrupt(DACDriver *dacp, uint32_t flags) { + + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA errors handling.*/ + dac_lld_stop_conversion(dacp); + _dac_isr_error_code(dacp, DAC_ERR_DMAFAILURE); + } + else { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _dac_isr_half_code(dacp); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _dac_isr_full_code(dacp); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level DAC driver initialization. + * + * @notapi + */ +void dac_lld_init(void) { + +#if STM32_DAC_USE_DAC1_CH1 + dacObjectInit(&DACD1); + DACD1.params = &dac1_ch1_params; + DACD1.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC1_CH2 + dacObjectInit(&DACD2); + DACD2.params = &dac1_ch2_params; + DACD2.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC2_CH1 + dacObjectInit(&DACD3); + DACD3.params = &dac2_ch1_params; + DACD3.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC2_CH2 + dacObjectInit(&DACD4); + DACD4.params = &dac2_ch2_params; + DACD4.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC3_CH1 + dacObjectInit(&DACD5); + DACD5.params = &dac3_ch1_params; + DACD5.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC3_CH2 + dacObjectInit(&DACD6); + DACD6.params = &dac3_ch2_params; + DACD6.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC4_CH1 + dacObjectInit(&DACD7); + DACD7.params = &dac4_ch1_params; + DACD7.dma = NULL; +#endif + +#if STM32_DAC_USE_DAC4_CH2 + dacObjectInit(&DACD8); + DACD8.params = &dac4_ch2_params; + DACD8.dma = NULL; +#endif +} + +/** + * @brief Configures and activates the DAC peripheral. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +void dac_lld_start(DACDriver *dacp) { + + /* If the driver is in DAC_STOP state then a full initialization is + required.*/ + if (dacp->state == DAC_STOP) { + dacchannel_t channel = 0; + + /* Enabling the clock source.*/ +#if STM32_DAC_USE_DAC1_CH1 + if (&DACD1 == dacp) { + rccEnableDAC1(true); + } +#endif + +#if STM32_DAC_USE_DAC1_CH2 + if (&DACD2 == dacp) { + rccEnableDAC1(true); + channel = 1; + } +#endif + +#if STM32_DAC_USE_DAC2_CH1 + if (&DACD3 == dacp) { + rccEnableDAC2(true); + } +#endif + +#if STM32_DAC_USE_DAC2_CH2 + if (&DACD4 == dacp) { + rccEnableDAC2(true); + channel = 1; + } +#endif + +#if STM32_DAC_USE_DAC3_CH1 + if (&DACD5 == dacp) { + rccEnableDAC3(true); + } +#endif + +#if STM32_DAC_USE_DAC3_CH2 + if (&DACD6 == dacp) { + rccEnableDAC3(true); + channel = 1; + } +#endif + +#if STM32_DAC_USE_DAC4_CH1 + if (&DACD7 == dacp) { + rccEnableDAC4(true); + } +#endif + +#if STM32_DAC_USE_DAC4_CH2 + if (&DACD8 == dacp) { + rccEnableDAC4(true); + channel = 1; + } +#endif + + /* Enabling DAC in SW triggering mode initially, initializing data to + zero.*/ +#if STM32_DAC_DUAL_MODE == FALSE + { + uint32_t cr; + + cr = dacp->params->dac->CR; + cr &= dacp->params->regmask; + cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift; + dacp->params->dac->CR = cr; + dac_lld_put_channel(dacp, channel, dacp->config->init); + } +#else + if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) || + (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) || + (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) { + dacp->params->dac->CR = DAC_CR_EN2 | (dacp->config->cr << 16) | DAC_CR_EN1 | dacp->config->cr; + dac_lld_put_channel(dacp, 1U, dacp->config->init); + } + else { + dacp->params->dac->CR = DAC_CR_EN1 | dacp->config->cr; + } + dac_lld_put_channel(dacp, channel, dacp->config->init); +#endif + } +} + +/** + * @brief Deactivates the DAC peripheral. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +void dac_lld_stop(DACDriver *dacp) { + + /* If in ready state then disables the DAC clock.*/ + if (dacp->state == DAC_READY) { + + /* Disabling DAC.*/ + dacp->params->dac->CR &= dacp->params->regmask; + +#if STM32_DAC_USE_DAC1_CH1 + if (&DACD1 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { + rccDisableDAC1(); + } + } +#endif + +#if STM32_DAC_USE_DAC1_CH2 + if (&DACD2 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { + rccDisableDAC1(); + } + } +#endif + +#if STM32_DAC_USE_DAC2_CH1 + if (&DACD3 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { + rccDisableDAC2(); + } + } +#endif + +#if STM32_DAC_USE_DAC2_CH2 + if (&DACD4 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { + rccDisableDAC2(); + } + } +#endif + +#if STM32_DAC_USE_DAC3_CH1 + if (&DACD5 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { + rccDisableDAC3(); + } + } +#endif + +#if STM32_DAC_USE_DAC3_CH2 + if (&DACD6 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { + rccDisableDAC3(); + } + } +#endif + +#if STM32_DAC_USE_DAC4_CH1 + if (&DACD7 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) { + rccDisableDAC4(); + } + } +#endif + +#if STM32_DAC_USE_DAC4_CH2 + if (&DACD8 == dacp) { + if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) { + rccDisableDAC4(); + } + } +#endif + } +} + +/** + * @brief Outputs a value directly on a DAC channel. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] channel DAC channel number + * @param[in] sample value to be output + * + * @api + */ +void dac_lld_put_channel(DACDriver *dacp, + dacchannel_t channel, + dacsample_t sample) { + + switch (dacp->config->datamode) { + case DAC_DHRM_12BIT_RIGHT: +#if STM32_DAC_DUAL_MODE + case DAC_DHRM_12BIT_RIGHT_DUAL: +#endif + if (channel == 0U) { +#if STM32_DAC_DUAL_MODE + dacp->params->dac->DHR12R1 = (uint32_t)sample; +#else + *(&dacp->params->dac->DHR12R1 + dacp->params->dataoffset) = (uint32_t)sample; +#endif + } +#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \ + STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2) + else { + dacp->params->dac->DHR12R2 = (uint32_t)sample; + } +#endif + break; + case DAC_DHRM_12BIT_LEFT: +#if STM32_DAC_DUAL_MODE + case DAC_DHRM_12BIT_LEFT_DUAL: +#endif + if (channel == 0U) { +#if STM32_DAC_DUAL_MODE + dacp->params->dac->DHR12L1 = (uint32_t)sample; +#else + *(&dacp->params->dac->DHR12L1 + dacp->params->dataoffset) = (uint32_t)sample; +#endif + } +#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \ + STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2) + else { + dacp->params->dac->DHR12L2 = (uint32_t)sample; + } +#endif + break; + case DAC_DHRM_8BIT_RIGHT: +#if STM32_DAC_DUAL_MODE + case DAC_DHRM_8BIT_RIGHT_DUAL: +#endif + if (channel == 0U) { +#if STM32_DAC_DUAL_MODE + dacp->params->dac->DHR8R1 = (uint32_t)sample; +#else + *(&dacp->params->dac->DHR8R1 + dacp->params->dataoffset) = (uint32_t)sample; +#endif + } +#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \ + STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2) + else { + dacp->params->dac->DHR8R2 = (uint32_t)sample; + } +#endif + break; + default: + osalDbgAssert(false, "unexpected DAC mode"); + break; + } +} + +/** + * @brief Starts a DAC conversion. + * @details Starts an asynchronous conversion operation. + * @note In @p DAC_DHRM_8BIT_RIGHT mode the parameters passed to the + * callback are wrong because two samples are packed in a single + * dacsample_t element. This will not be corrected, do not rely + * on those parameters. + * @note In @p DAC_DHRM_8BIT_RIGHT_DUAL mode two samples are treated + * as a single 16 bits sample and packed into a single dacsample_t + * element. The num_channels must be set to one in the group + * conversion configuration structure. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +void dac_lld_start_conversion(DACDriver *dacp) { + uint32_t n, cr, dmamode; + + /* Number of DMA operations per buffer.*/ + n = dacp->depth * dacp->grpp->num_channels; + + /* Allocating the DMA channel.*/ + dacp->dma = dmaStreamAllocI(dacp->params->dmastream, + dacp->params->dmairqprio, + (stm32_dmaisr_t)dac_lld_serve_tx_interrupt, + (void *)dacp); + osalDbgAssert(dacp->dma != NULL, "unable to allocate stream"); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(dacp->dma, dacp->params->peripheral); +#endif + + /* DMA settings depend on the chosen DAC mode.*/ + switch (dacp->config->datamode) { + /* Sets the DAC data register */ + case DAC_DHRM_12BIT_RIGHT: + osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); + + dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12R1 + + dacp->params->dataoffset); + dmamode = dacp->params->dmamode | +#if STM32_DMA_ADVANCED == FALSE + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_HWORD; +#else + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; +#endif + break; + case DAC_DHRM_12BIT_LEFT: + osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); + + dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12L1 + + dacp->params->dataoffset); + dmamode = dacp->params->dmamode | +#if STM32_DMA_ADVANCED == FALSE + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_HWORD; +#else + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; +#endif + break; + case DAC_DHRM_8BIT_RIGHT: + osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); + + dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR8R1 + + dacp->params->dataoffset); + dmamode = dacp->params->dmamode | +#if STM32_DMA_ADVANCED == FALSE + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_BYTE; +#else + STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; +#endif + + /* In this mode the size of the buffer is halved because two samples + packed in a single dacsample_t element.*/ + n = (n + 1) / 2; + break; +#if STM32_DAC_DUAL_MODE == TRUE + case DAC_DHRM_12BIT_RIGHT_DUAL: + osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels"); + + dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12RD); + dmamode = dacp->params->dmamode | + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; + n /= 2; + break; + case DAC_DHRM_12BIT_LEFT_DUAL: + osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels"); + + dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12LD); + dmamode = dacp->params->dmamode | + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; + n /= 2; + break; + case DAC_DHRM_8BIT_RIGHT_DUAL: + osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels"); + + dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR8RD); + dmamode = dacp->params->dmamode | +#if STM32_DMA_ADVANCED == FALSE + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_HWORD; +#else + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; +#endif + n /= 2; + break; +#endif + default: + osalDbgAssert(false, "unexpected DAC mode"); + return; + } + + dmaStreamSetMemory0(dacp->dma, dacp->samples); + dmaStreamSetTransactionSize(dacp->dma, n); + dmaStreamSetMode(dacp->dma, dmamode | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | + STM32_DMA_CR_HTIE | STM32_DMA_CR_TCIE); + dmaStreamEnable(dacp->dma); + + /* DAC configuration.*/ + cr = dacp->params->dac->CR; + +#if STM32_DAC_DUAL_MODE == FALSE + cr &= dacp->params->regmask; + cr |= (DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift; +#else + cr = DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr + | (dacp->grpp->trigger << DAC_CR_TSEL2_Pos) | DAC_CR_TEN2 | DAC_CR_EN2 | (dacp->config->cr << 16); +#endif + + dacp->params->dac->CR = cr; +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p DAC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @iclass + */ +void dac_lld_stop_conversion(DACDriver *dacp) { + uint32_t cr; + + /* DMA channel disabled and released.*/ + dmaStreamDisable(dacp->dma); + dmaStreamFreeI(dacp->dma); + dacp->dma = NULL; + + cr = dacp->params->dac->CR; + +#if STM32_DAC_DUAL_MODE == FALSE + cr &= dacp->params->regmask; + cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift; +#else + if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) || + (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) || + (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) { + cr = DAC_CR_EN2 | (dacp->config->cr << 16) | + DAC_CR_EN1 | dacp->config->cr; + } + else { + cr = DAC_CR_EN1 | dacp->config->cr; + } +#endif + + dacp->params->dac->CR = cr; +} + +#endif /* HAL_USE_DAC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h b/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h index 09550fae65..80672fa75c 100644 --- a/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h +++ b/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h @@ -1,662 +1,662 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file DACv1/hal_dac_lld.h - * @brief STM32 DAC subsystem low level driver header. - * - * @addtogroup DAC - * @{ - */ - -#ifndef HAL_DAC_LLD_H -#define HAL_DAC_LLD_H - -#if HAL_USE_DAC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name DAC trigger modes - * @{ - */ -#define DAC_TRG_MASK 7U -#define DAC_TRG(n) (n) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Enables the DAC dual mode. - * @note In dual mode DAC second channels cannot be accessed individually. - */ -#if !defined(STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) -#define STM32_DAC_DUAL_MODE FALSE -#endif - -/** - * @brief DAC1 CH1 driver enable switch. - * @details If set to @p TRUE the support for DAC1 channel 1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC1_CH1) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC1_CH1 FALSE -#endif - -/** - * @brief DAC1 CH2 driver enable switch. - * @details If set to @p TRUE the support for DAC1 channel 2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC1_CH2) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC1_CH2 FALSE -#endif - -/** - * @brief DAC2 CH1 driver enable switch. - * @details If set to @p TRUE the support for DAC2 channel 1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC2_CH1) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC2_CH1 FALSE -#endif - -/** - * @brief DAC2 CH2 driver enable switch. - * @details If set to @p TRUE the support for DAC2 channel 2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC2_CH2) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC2_CH2 FALSE -#endif - -/** - * @brief DAC3 CH1 driver enable switch. - * @details If set to @p TRUE the support for DAC3 channel 1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC3_CH1) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC3_CH1 FALSE -#endif - -/** - * @brief DAC3 CH2 driver enable switch. - * @details If set to @p TRUE the support for DAC3 channel 2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC3_CH2) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC3_CH2 FALSE -#endif - -/** - * @brief DAC4 CH1 driver enable switch. - * @details If set to @p TRUE the support for DAC4 channel 1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC4_CH1) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC4_CH1 FALSE -#endif - -/** - * @brief DAC4 CH2 driver enable switch. - * @details If set to @p TRUE the support for DAC4 channel 2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_DAC_USE_DAC4_CH2) || defined(__DOXYGEN__) -#define STM32_DAC_USE_DAC4_CH2 FALSE -#endif - -/** - * @brief DAC1 CH1 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC1_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC1 CH2 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC1_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC2 CH1 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC2_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC2_CH1_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC2 CH2 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC2_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC2_CH2_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC3 CH1 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC3_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC3 CH2 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC3_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC4 CH1 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC4_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC4_CH1_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC4 CH2 interrupt priority level setting. - */ -#if !defined(STM32_DAC_DAC4_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC4_CH2_IRQ_PRIORITY 10 -#endif - -/** - * @brief DAC1 CH1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC1_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC1 CH2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC1_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC2 CH1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC2_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC2_CH1_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC2 CH2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC2_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC2_CH2_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC3 CH1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC3_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC3 CH2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC3_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC4 CH1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC4_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC4_CH1_DMA_PRIORITY 2 -#endif - -/** - * @brief DAC4 CH2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_DAC_DAC4_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_DAC_DAC4_CH2_DMA_PRIORITY 2 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Handling missing registry keys.*/ -#if !defined(STM32_HAS_DAC1_CH1) -#define STM32_HAS_DAC1_CH1 FALSE -#endif -#if !defined(STM32_HAS_DAC1_CH2) -#define STM32_HAS_DAC1_CH2 FALSE -#endif -#if !defined(STM32_HAS_DAC2_CH1) -#define STM32_HAS_DAC2_CH1 FALSE -#endif -#if !defined(STM32_HAS_DAC2_CH2) -#define STM32_HAS_DAC2_CH2 FALSE -#endif -#if !defined(STM32_HAS_DAC3_CH1) -#define STM32_HAS_DAC3_CH1 FALSE -#endif -#if !defined(STM32_HAS_DAC3_CH2) -#define STM32_HAS_DAC3_CH2 FALSE -#endif -#if !defined(STM32_HAS_DAC4_CH1) -#define STM32_HAS_DAC4_CH1 FALSE -#endif -#if !defined(STM32_HAS_DAC4_CH2) -#define STM32_HAS_DAC4_CH2 FALSE -#endif - -#if STM32_DAC_USE_DAC1_CH1 && !STM32_HAS_DAC1_CH1 -#error "DAC1 CH1 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC1_CH2 && !STM32_HAS_DAC1_CH2 -#error "DAC1 CH2 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC2_CH1 && !STM32_HAS_DAC2_CH1 -#error "DAC2 CH1 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC2_CH2 && !STM32_HAS_DAC2_CH2 -#error "DAC2 CH2 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC3_CH1 && !STM32_HAS_DAC3_CH1 -#error "DAC3 CH1 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC3_CH2 && !STM32_HAS_DAC3_CH2 -#error "DAC3 CH2 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC4_CH1 && !STM32_HAS_DAC4_CH1 -#error "DAC4 CH1 not present in the selected device" -#endif - -#if STM32_DAC_USE_DAC4_CH2 && !STM32_HAS_DAC4_CH2 -#error "DAC4 CH2 not present in the selected device" -#endif - -#if (STM32_DAC_USE_DAC1_CH2 || STM32_DAC_USE_DAC2_CH2 || \ - STM32_DAC_USE_DAC3_CH2 || STM32_DAC_USE_DAC4_CH2) && STM32_DAC_DUAL_MODE -#error "DACx CH2 cannot be used independently in dual mode" -#endif - -#if !STM32_DAC_USE_DAC1_CH1 && !STM32_DAC_USE_DAC1_CH2 && \ - !STM32_DAC_USE_DAC2_CH1 && !STM32_DAC_USE_DAC2_CH2 && \ - !STM32_DAC_USE_DAC3_CH1 && !STM32_DAC_USE_DAC3_CH2 && \ - !STM32_DAC_USE_DAC4_CH1 && !STM32_DAC_USE_DAC4_CH2 -#error "DAC driver activated but no DAC peripheral assigned" -#endif - -#if STM32_DAC_USE_DAC1_CH1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC1 CH1" -#endif - -#if STM32_DAC_USE_DAC1_CH2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC1 CH2" -#endif - -#if STM32_DAC_USE_DAC2_CH1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC2 CH1" -#endif - -#if STM32_DAC_USE_DAC2_CH2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC2 CH2" -#endif - -#if STM32_DAC_USE_DAC3_CH1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC3 CH1" -#endif - -#if STM32_DAC_USE_DAC3_CH2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC3 CH2" -#endif - -#if STM32_DAC_USE_DAC4_CH1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC4 CH1" -#endif - -#if STM32_DAC_USE_DAC4_CH2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to DAC4 CH2" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_DAC_USE_DAC1_CH1 && !defined(STM32_DAC_DAC1_CH1_DMA_STREAM) -#error "DAC1 CH1 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC1_CH2 && !defined(STM32_DAC_DAC1_CH2_DMA_STREAM) -#error "DAC1 CH2 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC2_CH1 && !defined(STM32_DAC_DAC2_CH1_DMA_STREAM) -#error "DAC2 CH1 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC2_CH2 && !defined(STM32_DAC_DAC2_CH2_DMA_STREAM) -#error "DAC2 CH2 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC3_CH1 && !defined(STM32_DAC_DAC3_CH1_DMA_STREAM) -#error "DAC3 CH1 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC3_CH2 && !defined(STM32_DAC_DAC3_CH2_DMA_STREAM) -#error "DAC3 CH2 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC4_CH1 && !defined(STM32_DAC_DAC4_CH1_DMA_STREAM) -#error "DAC4 CH1 DMA stream not defined" -#endif - -#if STM32_DAC_USE_DAC4_CH2 && !defined(STM32_DAC_DAC4_CH2_DMA_STREAM) -#error "DAC4 CH2 DMA stream not defined" -#endif - -#if STM32_DMA_SUPPORTS_DMAMUX - -#else /* !STM32_DMA_SUPPORTS_DMAMUX */ - -/* Check on the validity of the assigned DMA streams.*/ -#if STM32_DAC_USE_DAC1_CH1 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC1_CH1_DMA_STREAM, STM32_DAC1_CH1_DMA_MSK) -#error "invalid DMA stream associated to DAC1 CH1" -#endif - -#if STM32_DAC_USE_DAC1_CH2 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC1_CH2_DMA_STREAM, STM32_DAC1_CH2_DMA_MSK) -#error "invalid DMA stream associated to DAC1 CH2" -#endif - -#if STM32_DAC_USE_DAC2_CH1 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC2_CH1_DMA_STREAM, STM32_DAC2_CH1_DMA_MSK) -#error "invalid DMA stream associated to DAC2 CH1" -#endif - -#if STM32_DAC_USE_DAC2_CH2 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC2_CH2_DMA_STREAM, STM32_DAC2_CH2_DMA_MSK) -#error "invalid DMA stream associated to DAC2 CH2" -#endif - -#if STM32_DAC_USE_DAC3_CH1 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC3_CH1_DMA_STREAM, STM32_DAC3_CH1_DMA_MSK) -#error "invalid DMA stream associated to DAC1 CH1" -#endif - -#if STM32_DAC_USE_DAC3_CH2 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC3_CH2_DMA_STREAM, STM32_DAC3_CH2_DMA_MSK) -#error "invalid DMA stream associated to DAC1 CH2" -#endif - -#if STM32_DAC_USE_DAC4_CH1 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC4_CH1_DMA_STREAM, STM32_DAC4_CH1_DMA_MSK) -#error "invalid DMA stream associated to DAC2 CH1" -#endif - -#if STM32_DAC_USE_DAC4_CH2 && \ - !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC4_CH2_DMA_STREAM, STM32_DAC4_CH2_DMA_MSK) -#error "invalid DMA stream associated to DAC2 CH2" -#endif - -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -#endif /* STM32_ADVANCED_DMA */ - -#if STM32_DAC_USE_DAC1_CH1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC1 CH1" -#endif - -#if STM32_DAC_USE_DAC1_CH2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC1 CH2" -#endif - -#if STM32_DAC_USE_DAC2_CH1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC2 CH1" -#endif - -#if STM32_DAC_USE_DAC2_CH2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC2 CH2" -#endif - -#if STM32_DAC_USE_DAC3_CH1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC3 CH1" -#endif - -#if STM32_DAC_USE_DAC3_CH2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC3 CH2" -#endif - -#if STM32_DAC_USE_DAC4_CH1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC4 CH1" -#endif - -#if STM32_DAC_USE_DAC4_CH2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to DAC4 CH2" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/** - * @brief Max DAC channels. - */ -#if STM32_DAC_DUAL_MODE == FALSE -#define DAC_MAX_CHANNELS 2 -#else -#define DAC_MAX_CHANNELS 1 -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a DAC channel index. - */ -typedef uint32_t dacchannel_t; - -/** - * @brief Type representing a DAC sample. - */ -typedef uint16_t dacsample_t; - -/** - * @brief DAC channel parameters type. - */ -typedef struct { - /** - * @brief Pointer to the DAC registers block. - */ - DAC_TypeDef *dac; - /** - * @brief DAC data registers offset. - */ - uint32_t dataoffset; - /** - * @brief DAC CR register bit offset. - */ - uint32_t regshift; - /** - * @brief DAC CR register mask. - */ - uint32_t regmask; - /** - * @brief Associated DMA stream. - */ - uint32_t dmastream; - /** - * @brief Mode bits for the DMA. - */ - uint32_t dmamode; - /** - * @brief DMA channel IRQ priority. - */ - uint32_t dmairqprio; -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) - /** - * @brief DMAMUX peripheral selector. - */ - uint32_t peripheral; -#endif -} dacparams_t; - -/** - * @brief Possible DAC failure causes. - * @note Error codes are architecture dependent and should not relied - * upon. - */ -typedef enum { - DAC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ - DAC_ERR_UNDERFLOW = 1 /**< DAC overflow condition. */ -} dacerror_t; - -/** - * @brief Samples alignment and size mode. - */ -typedef enum { - DAC_DHRM_12BIT_RIGHT = 0, - DAC_DHRM_12BIT_LEFT = 1, - DAC_DHRM_8BIT_RIGHT = 2, -#if STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) - DAC_DHRM_12BIT_RIGHT_DUAL = 3, - DAC_DHRM_12BIT_LEFT_DUAL = 4, - DAC_DHRM_8BIT_RIGHT_DUAL = 5 -#endif -} dacdhrmode_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the DAC driver structure. - */ -#define dac_lld_driver_fields \ - /* DAC channel parameters.*/ \ - const dacparams_t *params; \ - /* Associated DMA.*/ \ - const stm32_dma_stream_t *dma - -/** - * @brief Low level fields of the DAC configuration structure. - */ -#define dac_lld_config_fields \ - /* Initial output on DAC channels.*/ \ - dacsample_t init; \ - /* DAC data holding register mode.*/ \ - dacdhrmode_t datamode; \ - /* DAC control register lower 16 bits.*/ \ - uint32_t cr - -/** - * @brief Low level fields of the DAC group configuration structure. - */ -#define dac_lld_conversion_group_fields \ - /* DAC initialization data. This field contains the (not shifted) value \ - to be put into the TSEL field of the DAC CR register during \ - initialization. All other fields are handled internally.*/ \ - uint32_t trigger - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_DAC_USE_DAC1_CH1 && !defined(__DOXYGEN__) -extern DACDriver DACD1; -#endif - -#if STM32_DAC_USE_DAC1_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) -extern DACDriver DACD2; -#endif - -#if STM32_DAC_USE_DAC2_CH1 && !defined(__DOXYGEN__) -extern DACDriver DACD3; -#endif - -#if STM32_DAC_USE_DAC2_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) -extern DACDriver DACD4; -#endif - -#if STM32_DAC_USE_DAC3_CH1 && !defined(__DOXYGEN__) -extern DACDriver DACD5; -#endif - -#if STM32_DAC_USE_DAC3_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) -extern DACDriver DACD6; -#endif - -#if STM32_DAC_USE_DAC4_CH1 && !defined(__DOXYGEN__) -extern DACDriver DACD7; -#endif - -#if STM32_DAC_USE_DAC4_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) -extern DACDriver DACD8; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dac_lld_init(void); - void dac_lld_start(DACDriver *dacp); - void dac_lld_stop(DACDriver *dacp); - void dac_lld_put_channel(DACDriver *dacp, - dacchannel_t channel, - dacsample_t sample); - void dac_lld_start_conversion(DACDriver *dacp); - void dac_lld_stop_conversion(DACDriver *dacp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_DAC */ - -#endif /* HAL_DAC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file DACv1/hal_dac_lld.h + * @brief STM32 DAC subsystem low level driver header. + * + * @addtogroup DAC + * @{ + */ + +#ifndef HAL_DAC_LLD_H +#define HAL_DAC_LLD_H + +#if HAL_USE_DAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name DAC trigger modes + * @{ + */ +#define DAC_TRG_MASK 7U +#define DAC_TRG(n) (n) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Enables the DAC dual mode. + * @note In dual mode DAC second channels cannot be accessed individually. + */ +#if !defined(STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__) +#define STM32_DAC_DUAL_MODE FALSE +#endif + +/** + * @brief DAC1 CH1 driver enable switch. + * @details If set to @p TRUE the support for DAC1 channel 1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC1_CH1) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC1_CH1 FALSE +#endif + +/** + * @brief DAC1 CH2 driver enable switch. + * @details If set to @p TRUE the support for DAC1 channel 2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC1_CH2) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC1_CH2 FALSE +#endif + +/** + * @brief DAC2 CH1 driver enable switch. + * @details If set to @p TRUE the support for DAC2 channel 1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC2_CH1) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC2_CH1 FALSE +#endif + +/** + * @brief DAC2 CH2 driver enable switch. + * @details If set to @p TRUE the support for DAC2 channel 2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC2_CH2) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC2_CH2 FALSE +#endif + +/** + * @brief DAC3 CH1 driver enable switch. + * @details If set to @p TRUE the support for DAC3 channel 1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC3_CH1) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC3_CH1 FALSE +#endif + +/** + * @brief DAC3 CH2 driver enable switch. + * @details If set to @p TRUE the support for DAC3 channel 2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC3_CH2) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC3_CH2 FALSE +#endif + +/** + * @brief DAC4 CH1 driver enable switch. + * @details If set to @p TRUE the support for DAC4 channel 1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC4_CH1) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC4_CH1 FALSE +#endif + +/** + * @brief DAC4 CH2 driver enable switch. + * @details If set to @p TRUE the support for DAC4 channel 2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_DAC_USE_DAC4_CH2) || defined(__DOXYGEN__) +#define STM32_DAC_USE_DAC4_CH2 FALSE +#endif + +/** + * @brief DAC1 CH1 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC1_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC1 CH2 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC1_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC2 CH1 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC2_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC2_CH1_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC2 CH2 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC2_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC2_CH2_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC3 CH1 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC3_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC3 CH2 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC3_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC4 CH1 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC4_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC4_CH1_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC4 CH2 interrupt priority level setting. + */ +#if !defined(STM32_DAC_DAC4_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC4_CH2_IRQ_PRIORITY 10 +#endif + +/** + * @brief DAC1 CH1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC1_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC1 CH2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC1_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC2 CH1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC2_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC2_CH1_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC2 CH2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC2_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC2_CH2_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC3 CH1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC3_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC3 CH2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC3_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC4 CH1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC4_CH1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC4_CH1_DMA_PRIORITY 2 +#endif + +/** + * @brief DAC4 CH2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_DAC_DAC4_CH2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_DAC_DAC4_CH2_DMA_PRIORITY 2 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Handling missing registry keys.*/ +#if !defined(STM32_HAS_DAC1_CH1) +#define STM32_HAS_DAC1_CH1 FALSE +#endif +#if !defined(STM32_HAS_DAC1_CH2) +#define STM32_HAS_DAC1_CH2 FALSE +#endif +#if !defined(STM32_HAS_DAC2_CH1) +#define STM32_HAS_DAC2_CH1 FALSE +#endif +#if !defined(STM32_HAS_DAC2_CH2) +#define STM32_HAS_DAC2_CH2 FALSE +#endif +#if !defined(STM32_HAS_DAC3_CH1) +#define STM32_HAS_DAC3_CH1 FALSE +#endif +#if !defined(STM32_HAS_DAC3_CH2) +#define STM32_HAS_DAC3_CH2 FALSE +#endif +#if !defined(STM32_HAS_DAC4_CH1) +#define STM32_HAS_DAC4_CH1 FALSE +#endif +#if !defined(STM32_HAS_DAC4_CH2) +#define STM32_HAS_DAC4_CH2 FALSE +#endif + +#if STM32_DAC_USE_DAC1_CH1 && !STM32_HAS_DAC1_CH1 +#error "DAC1 CH1 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC1_CH2 && !STM32_HAS_DAC1_CH2 +#error "DAC1 CH2 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC2_CH1 && !STM32_HAS_DAC2_CH1 +#error "DAC2 CH1 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC2_CH2 && !STM32_HAS_DAC2_CH2 +#error "DAC2 CH2 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC3_CH1 && !STM32_HAS_DAC3_CH1 +#error "DAC3 CH1 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC3_CH2 && !STM32_HAS_DAC3_CH2 +#error "DAC3 CH2 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC4_CH1 && !STM32_HAS_DAC4_CH1 +#error "DAC4 CH1 not present in the selected device" +#endif + +#if STM32_DAC_USE_DAC4_CH2 && !STM32_HAS_DAC4_CH2 +#error "DAC4 CH2 not present in the selected device" +#endif + +#if (STM32_DAC_USE_DAC1_CH2 || STM32_DAC_USE_DAC2_CH2 || \ + STM32_DAC_USE_DAC3_CH2 || STM32_DAC_USE_DAC4_CH2) && STM32_DAC_DUAL_MODE +#error "DACx CH2 cannot be used independently in dual mode" +#endif + +#if !STM32_DAC_USE_DAC1_CH1 && !STM32_DAC_USE_DAC1_CH2 && \ + !STM32_DAC_USE_DAC2_CH1 && !STM32_DAC_USE_DAC2_CH2 && \ + !STM32_DAC_USE_DAC3_CH1 && !STM32_DAC_USE_DAC3_CH2 && \ + !STM32_DAC_USE_DAC4_CH1 && !STM32_DAC_USE_DAC4_CH2 +#error "DAC driver activated but no DAC peripheral assigned" +#endif + +#if STM32_DAC_USE_DAC1_CH1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC1 CH1" +#endif + +#if STM32_DAC_USE_DAC1_CH2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC1 CH2" +#endif + +#if STM32_DAC_USE_DAC2_CH1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC2 CH1" +#endif + +#if STM32_DAC_USE_DAC2_CH2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC2 CH2" +#endif + +#if STM32_DAC_USE_DAC3_CH1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC3 CH1" +#endif + +#if STM32_DAC_USE_DAC3_CH2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC3 CH2" +#endif + +#if STM32_DAC_USE_DAC4_CH1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC4 CH1" +#endif + +#if STM32_DAC_USE_DAC4_CH2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to DAC4 CH2" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_DAC_USE_DAC1_CH1 && !defined(STM32_DAC_DAC1_CH1_DMA_STREAM) +#error "DAC1 CH1 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC1_CH2 && !defined(STM32_DAC_DAC1_CH2_DMA_STREAM) +#error "DAC1 CH2 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC2_CH1 && !defined(STM32_DAC_DAC2_CH1_DMA_STREAM) +#error "DAC2 CH1 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC2_CH2 && !defined(STM32_DAC_DAC2_CH2_DMA_STREAM) +#error "DAC2 CH2 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC3_CH1 && !defined(STM32_DAC_DAC3_CH1_DMA_STREAM) +#error "DAC3 CH1 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC3_CH2 && !defined(STM32_DAC_DAC3_CH2_DMA_STREAM) +#error "DAC3 CH2 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC4_CH1 && !defined(STM32_DAC_DAC4_CH1_DMA_STREAM) +#error "DAC4 CH1 DMA stream not defined" +#endif + +#if STM32_DAC_USE_DAC4_CH2 && !defined(STM32_DAC_DAC4_CH2_DMA_STREAM) +#error "DAC4 CH2 DMA stream not defined" +#endif + +#if STM32_DMA_SUPPORTS_DMAMUX + +#else /* !STM32_DMA_SUPPORTS_DMAMUX */ + +/* Check on the validity of the assigned DMA streams.*/ +#if STM32_DAC_USE_DAC1_CH1 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC1_CH1_DMA_STREAM, STM32_DAC1_CH1_DMA_MSK) +#error "invalid DMA stream associated to DAC1 CH1" +#endif + +#if STM32_DAC_USE_DAC1_CH2 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC1_CH2_DMA_STREAM, STM32_DAC1_CH2_DMA_MSK) +#error "invalid DMA stream associated to DAC1 CH2" +#endif + +#if STM32_DAC_USE_DAC2_CH1 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC2_CH1_DMA_STREAM, STM32_DAC2_CH1_DMA_MSK) +#error "invalid DMA stream associated to DAC2 CH1" +#endif + +#if STM32_DAC_USE_DAC2_CH2 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC2_CH2_DMA_STREAM, STM32_DAC2_CH2_DMA_MSK) +#error "invalid DMA stream associated to DAC2 CH2" +#endif + +#if STM32_DAC_USE_DAC3_CH1 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC3_CH1_DMA_STREAM, STM32_DAC3_CH1_DMA_MSK) +#error "invalid DMA stream associated to DAC1 CH1" +#endif + +#if STM32_DAC_USE_DAC3_CH2 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC3_CH2_DMA_STREAM, STM32_DAC3_CH2_DMA_MSK) +#error "invalid DMA stream associated to DAC1 CH2" +#endif + +#if STM32_DAC_USE_DAC4_CH1 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC4_CH1_DMA_STREAM, STM32_DAC4_CH1_DMA_MSK) +#error "invalid DMA stream associated to DAC2 CH1" +#endif + +#if STM32_DAC_USE_DAC4_CH2 && \ + !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC4_CH2_DMA_STREAM, STM32_DAC4_CH2_DMA_MSK) +#error "invalid DMA stream associated to DAC2 CH2" +#endif + +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +#endif /* STM32_ADVANCED_DMA */ + +#if STM32_DAC_USE_DAC1_CH1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC1 CH1" +#endif + +#if STM32_DAC_USE_DAC1_CH2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC1 CH2" +#endif + +#if STM32_DAC_USE_DAC2_CH1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC2 CH1" +#endif + +#if STM32_DAC_USE_DAC2_CH2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC2 CH2" +#endif + +#if STM32_DAC_USE_DAC3_CH1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC3 CH1" +#endif + +#if STM32_DAC_USE_DAC3_CH2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC3 CH2" +#endif + +#if STM32_DAC_USE_DAC4_CH1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC4 CH1" +#endif + +#if STM32_DAC_USE_DAC4_CH2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to DAC4 CH2" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/** + * @brief Max DAC channels. + */ +#if STM32_DAC_DUAL_MODE == FALSE +#define DAC_MAX_CHANNELS 2 +#else +#define DAC_MAX_CHANNELS 1 +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a DAC channel index. + */ +typedef uint32_t dacchannel_t; + +/** + * @brief Type representing a DAC sample. + */ +typedef uint16_t dacsample_t; + +/** + * @brief DAC channel parameters type. + */ +typedef struct { + /** + * @brief Pointer to the DAC registers block. + */ + DAC_TypeDef *dac; + /** + * @brief DAC data registers offset. + */ + uint32_t dataoffset; + /** + * @brief DAC CR register bit offset. + */ + uint32_t regshift; + /** + * @brief DAC CR register mask. + */ + uint32_t regmask; + /** + * @brief Associated DMA stream. + */ + uint32_t dmastream; + /** + * @brief Mode bits for the DMA. + */ + uint32_t dmamode; + /** + * @brief DMA channel IRQ priority. + */ + uint32_t dmairqprio; +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) + /** + * @brief DMAMUX peripheral selector. + */ + uint32_t peripheral; +#endif +} dacparams_t; + +/** + * @brief Possible DAC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + DAC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ + DAC_ERR_UNDERFLOW = 1 /**< DAC overflow condition. */ +} dacerror_t; + +/** + * @brief Samples alignment and size mode. + */ +typedef enum { + DAC_DHRM_12BIT_RIGHT = 0, + DAC_DHRM_12BIT_LEFT = 1, + DAC_DHRM_8BIT_RIGHT = 2, +#if STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) + DAC_DHRM_12BIT_RIGHT_DUAL = 3, + DAC_DHRM_12BIT_LEFT_DUAL = 4, + DAC_DHRM_8BIT_RIGHT_DUAL = 5 +#endif +} dacdhrmode_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the DAC driver structure. + */ +#define dac_lld_driver_fields \ + /* DAC channel parameters.*/ \ + const dacparams_t *params; \ + /* Associated DMA.*/ \ + const stm32_dma_stream_t *dma + +/** + * @brief Low level fields of the DAC configuration structure. + */ +#define dac_lld_config_fields \ + /* Initial output on DAC channels.*/ \ + dacsample_t init; \ + /* DAC data holding register mode.*/ \ + dacdhrmode_t datamode; \ + /* DAC control register lower 16 bits.*/ \ + uint32_t cr + +/** + * @brief Low level fields of the DAC group configuration structure. + */ +#define dac_lld_conversion_group_fields \ + /* DAC initialization data. This field contains the (not shifted) value \ + to be put into the TSEL field of the DAC CR register during \ + initialization. All other fields are handled internally.*/ \ + uint32_t trigger + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_DAC_USE_DAC1_CH1 && !defined(__DOXYGEN__) +extern DACDriver DACD1; +#endif + +#if STM32_DAC_USE_DAC1_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) +extern DACDriver DACD2; +#endif + +#if STM32_DAC_USE_DAC2_CH1 && !defined(__DOXYGEN__) +extern DACDriver DACD3; +#endif + +#if STM32_DAC_USE_DAC2_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) +extern DACDriver DACD4; +#endif + +#if STM32_DAC_USE_DAC3_CH1 && !defined(__DOXYGEN__) +extern DACDriver DACD5; +#endif + +#if STM32_DAC_USE_DAC3_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) +extern DACDriver DACD6; +#endif + +#if STM32_DAC_USE_DAC4_CH1 && !defined(__DOXYGEN__) +extern DACDriver DACD7; +#endif + +#if STM32_DAC_USE_DAC4_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__) +extern DACDriver DACD8; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dac_lld_init(void); + void dac_lld_start(DACDriver *dacp); + void dac_lld_stop(DACDriver *dacp); + void dac_lld_put_channel(DACDriver *dacp, + dacchannel_t channel, + dacsample_t sample); + void dac_lld_start_conversion(DACDriver *dacp); + void dac_lld_stop_conversion(DACDriver *dacp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_DAC */ + +#endif /* HAL_DAC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/DMAv1/driver.mk b/os/hal/ports/STM32/LLD/DMAv1/driver.mk index 6080cec58f..b4be3ab9da 100644 --- a/os/hal/ports/STM32/LLD/DMAv1/driver.mk +++ b/os/hal/ports/STM32/LLD/DMAv1/driver.mk @@ -1,2 +1,2 @@ -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1 diff --git a/os/hal/ports/STM32/LLD/DMAv1/notes.txt b/os/hal/ports/STM32/LLD/DMAv1/notes.txt index dc46638904..562f45fb52 100644 --- a/os/hal/ports/STM32/LLD/DMAv1/notes.txt +++ b/os/hal/ports/STM32/LLD/DMAv1/notes.txt @@ -1,26 +1,26 @@ -STM32 DMAv1 driver. - -Driver capability: - -- The driver supports the STM32 traditional DMA controller in the following - configurations: 5ch, 7ch, 7ch+5ch, 7ch+7ch. -- Support for automatic the channel selection through the CSELR register. -- For devices without CSELR register it is possible to select channels but - the SYSCFG CFGR register is not configured, the user has to configure it - before starting the DMA driver. -- The driver supports shared ISR handlers with a quirk: the IRQ priority is - established by the first allocated channel among the channels sharing the - ISR. - -The file registry must export: - -STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other - drivers use it to enable checks on DMA - channels. Probably will be removed in the - future. -STM32_DMA_SUPPORTS_CSELR - TRUE if the DMA have a CSELR register. -STM32_DMA_SUPPORTS_DMAMUX - TRUE if the DMA is riven by a DMAMUX. -STM32_DMAn_NUM_CHANNELS - Number of channels in DMAs "n" (1..2). -STM32_DMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro - is not exported then the ISR is not declared. -STM32_DMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7). +STM32 DMAv1 driver. + +Driver capability: + +- The driver supports the STM32 traditional DMA controller in the following + configurations: 5ch, 7ch, 7ch+5ch, 7ch+7ch. +- Support for automatic the channel selection through the CSELR register. +- For devices without CSELR register it is possible to select channels but + the SYSCFG CFGR register is not configured, the user has to configure it + before starting the DMA driver. +- The driver supports shared ISR handlers with a quirk: the IRQ priority is + established by the first allocated channel among the channels sharing the + ISR. + +The file registry must export: + +STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other + drivers use it to enable checks on DMA + channels. Probably will be removed in the + future. +STM32_DMA_SUPPORTS_CSELR - TRUE if the DMA have a CSELR register. +STM32_DMA_SUPPORTS_DMAMUX - TRUE if the DMA is riven by a DMAMUX. +STM32_DMAn_NUM_CHANNELS - Number of channels in DMAs "n" (1..2). +STM32_DMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro + is not exported then the ISR is not declared. +STM32_DMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7). diff --git a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c index 955e557af1..65fa5e8bc5 100644 --- a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c +++ b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c @@ -1,816 +1,816 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file DMAv1/stm32_dma.c - * @brief DMA helper driver code. - * - * @addtogroup STM32_DMA - * @details DMA sharing helper driver. In the STM32 the DMA streams are a - * shared resource, this driver allows to allocate and free DMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating streams. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring DMA services - has been enabled.*/ -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the DMA1 streams in @p dma_streams_mask. - */ -#define STM32_DMA1_STREAMS_MASK ((1U << STM32_DMA1_NUM_CHANNELS) - 1U) - -/** - * @brief Mask of the DMA2 streams in @p dma_streams_mask. - */ -#define STM32_DMA2_STREAMS_MASK (((1U << STM32_DMA2_NUM_CHANNELS) - \ - 1U) << STM32_DMA1_NUM_CHANNELS) - -#if STM32_DMA_SUPPORTS_CSELR == TRUE - -#if defined(DMA1_CSELR) -#define __DMA1_CSELR &DMA1_CSELR->CSELR -#else -#define __DMA1_CSELR &DMA1->CSELR -#endif - -#if defined(DMA2_CSELR) -#define __DMA2_CSELR &DMA2_CSELR->CSELR -#else -#define __DMA2_CSELR &DMA2->CSELR -#endif - -#define DMA1_CH1_VARIANT __DMA1_CSELR -#define DMA1_CH2_VARIANT __DMA1_CSELR -#define DMA1_CH3_VARIANT __DMA1_CSELR -#define DMA1_CH4_VARIANT __DMA1_CSELR -#define DMA1_CH5_VARIANT __DMA1_CSELR -#define DMA1_CH6_VARIANT __DMA1_CSELR -#define DMA1_CH7_VARIANT __DMA1_CSELR -#define DMA1_CH8_VARIANT __DMA1_CSELR -#define DMA2_CH1_VARIANT __DMA2_CSELR -#define DMA2_CH2_VARIANT __DMA2_CSELR -#define DMA2_CH3_VARIANT __DMA2_CSELR -#define DMA2_CH4_VARIANT __DMA2_CSELR -#define DMA2_CH5_VARIANT __DMA2_CSELR -#define DMA2_CH6_VARIANT __DMA2_CSELR -#define DMA2_CH7_VARIANT __DMA2_CSELR -#define DMA2_CH8_VARIANT __DMA2_CSELR - -#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE - -#define DMAMUX1_CHANNEL(id) (DMAMUX1_BASE + ((id) * 4U)) - -#define DMA1_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0)) -#define DMA1_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1)) -#define DMA1_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2)) -#define DMA1_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3)) -#define DMA1_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4)) -#define DMA1_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5)) -#define DMA1_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6)) -#define DMA1_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7)) -#define DMA2_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6 + STM32_DMA1_NUM_CHANNELS)) -#define DMA2_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7 + STM32_DMA1_NUM_CHANNELS)) - -#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ - -#define DMA1_CH1_VARIANT 0 -#define DMA1_CH2_VARIANT 0 -#define DMA1_CH3_VARIANT 0 -#define DMA1_CH4_VARIANT 0 -#define DMA1_CH5_VARIANT 0 -#define DMA1_CH6_VARIANT 0 -#define DMA1_CH7_VARIANT 0 -#define DMA2_CH1_VARIANT 0 -#define DMA2_CH2_VARIANT 0 -#define DMA2_CH3_VARIANT 0 -#define DMA2_CH4_VARIANT 0 -#define DMA2_CH5_VARIANT 0 -#define DMA2_CH6_VARIANT 0 -#define DMA2_CH7_VARIANT 0 - -#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ - -/* - * Default ISR collision masks. - */ -#if !defined(STM32_DMA1_CH1_CMASK) -#define STM32_DMA1_CH1_CMASK (1U << 0U) -#endif - -#if !defined(STM32_DMA1_CH2_CMASK) -#define STM32_DMA1_CH2_CMASK (1U << 1U) -#endif - -#if !defined(STM32_DMA1_CH3_CMASK) -#define STM32_DMA1_CH3_CMASK (1U << 2U) -#endif - -#if !defined(STM32_DMA1_CH4_CMASK) -#define STM32_DMA1_CH4_CMASK (1U << 3U) -#endif - -#if !defined(STM32_DMA1_CH5_CMASK) -#define STM32_DMA1_CH5_CMASK (1U << 4U) -#endif - -#if !defined(STM32_DMA1_CH6_CMASK) -#define STM32_DMA1_CH6_CMASK (1U << 5U) -#endif - -#if !defined(STM32_DMA1_CH7_CMASK) -#define STM32_DMA1_CH7_CMASK (1U << 6U) -#endif - -#if !defined(STM32_DMA1_CH8_CMASK) -#define STM32_DMA1_CH8_CMASK (1U << 7U) -#endif - -#if !defined(STM32_DMA2_CH1_CMASK) -#define STM32_DMA2_CH1_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 0U)) -#endif - -#if !defined(STM32_DMA2_CH2_CMASK) -#define STM32_DMA2_CH2_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 1U)) -#endif - -#if !defined(STM32_DMA2_CH3_CMASK) -#define STM32_DMA2_CH3_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 2U)) -#endif - -#if !defined(STM32_DMA2_CH4_CMASK) -#define STM32_DMA2_CH4_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 3U)) -#endif - -#if !defined(STM32_DMA2_CH5_CMASK) -#define STM32_DMA2_CH5_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 4U)) -#endif - -#if !defined(STM32_DMA2_CH6_CMASK) -#define STM32_DMA2_CH6_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 5U)) -#endif - -#if !defined(STM32_DMA2_CH7_CMASK) -#define STM32_DMA2_CH7_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 6U)) -#endif - -#if !defined(STM32_DMA2_CH8_CMASK) -#define STM32_DMA2_CH8_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 7U)) -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief DMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. - */ -const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { -#if STM32_DMA1_NUM_CHANNELS > 0 - {DMA1, DMA1_Channel1, STM32_DMA1_CH1_CMASK, DMA1_CH1_VARIANT, 0, 0, STM32_DMA1_CH1_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 1 - {DMA1, DMA1_Channel2, STM32_DMA1_CH2_CMASK, DMA1_CH2_VARIANT, 4, 1, STM32_DMA1_CH2_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 2 - {DMA1, DMA1_Channel3, STM32_DMA1_CH3_CMASK, DMA1_CH3_VARIANT, 8, 2, STM32_DMA1_CH3_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 3 - {DMA1, DMA1_Channel4, STM32_DMA1_CH4_CMASK, DMA1_CH4_VARIANT, 12, 3, STM32_DMA1_CH4_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 4 - {DMA1, DMA1_Channel5, STM32_DMA1_CH5_CMASK, DMA1_CH5_VARIANT, 16, 4, STM32_DMA1_CH5_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 5 - {DMA1, DMA1_Channel6, STM32_DMA1_CH6_CMASK, DMA1_CH6_VARIANT, 20, 5, STM32_DMA1_CH6_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 6 - {DMA1, DMA1_Channel7, STM32_DMA1_CH7_CMASK, DMA1_CH7_VARIANT, 24, 6, STM32_DMA1_CH7_NUMBER}, -#endif -#if STM32_DMA1_NUM_CHANNELS > 7 - {DMA1, DMA1_Channel8, STM32_DMA1_CH8_CMASK, DMA1_CH8_VARIANT, 28, 7, STM32_DMA1_CH8_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 0 - {DMA2, DMA2_Channel1, STM32_DMA2_CH1_CMASK, DMA2_CH1_VARIANT, 0, 0 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH1_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 1 - {DMA2, DMA2_Channel2, STM32_DMA2_CH2_CMASK, DMA2_CH2_VARIANT, 4, 1 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH2_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 2 - {DMA2, DMA2_Channel3, STM32_DMA2_CH3_CMASK, DMA2_CH3_VARIANT, 8, 2 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH3_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 3 - {DMA2, DMA2_Channel4, STM32_DMA2_CH4_CMASK, DMA2_CH4_VARIANT, 12, 3 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH4_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 4 - {DMA2, DMA2_Channel5, STM32_DMA2_CH5_CMASK, DMA2_CH5_VARIANT, 16, 4 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH5_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 5 - {DMA2, DMA2_Channel6, STM32_DMA2_CH6_CMASK, DMA2_CH6_VARIANT, 20, 5 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH6_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 6 - {DMA2, DMA2_Channel7, STM32_DMA2_CH7_CMASK, DMA2_CH7_VARIANT, 24, 6 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH7_NUMBER}, -#endif -#if STM32_DMA2_NUM_CHANNELS > 7 - {DMA2, DMA2_Channel8, STM32_DMA2_CH8_CMASK, DMA2_CH8_VARIANT, 28, 7 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH8_NUMBER}, -#endif -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Global DMA-related data structures. - */ -static struct { - /** - * @brief Mask of the allocated streams. - */ - uint32_t allocated_mask; - /** - * @brief Mask of the enabled streams ISRs. - */ - uint32_t isr_mask; - /** - * @brief DMA IRQ redirectors. - */ - struct { - /** - * @brief DMA callback function. - */ - stm32_dmaisr_t func; - /** - * @brief DMA callback parameter. - */ - void *param; - } streams[STM32_DMA_STREAMS]; -} dma; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if defined(STM32_DMA1_CH1_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 1 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH2_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 2 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH3_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 3 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH4_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 4 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH5_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 5 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM5); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH6_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 6 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM6); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH7_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 7 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM7); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA1_CH8_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 stream 8 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA1_STREAM8); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH1_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 1 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH2_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 2 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH3_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 3 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH4_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 4 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH5_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 5 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM5); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH6_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 6 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM6); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH7_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 7 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM7); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if defined(STM32_DMA2_CH8_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 stream 8 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - dmaServeInterrupt(STM32_DMA2_STREAM8); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA helper initialization. - * - * @init - */ -void dmaInit(void) { - int i; - - dma.allocated_mask = 0U; - dma.isr_mask = 0U; - for (i = 0; i < STM32_DMA_STREAMS; i++) { - _stm32_dma_streams[i].channel->CCR = STM32_DMA_CCR_RESET_VALUE; - dma.streams[i].func = NULL; - } - DMA1->IFCR = 0xFFFFFFFFU; -#if STM32_DMA2_NUM_CHANNELS > 0 - DMA2->IFCR = 0xFFFFFFFFU; -#endif -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific stream or: - * - @p STM32_DMA_STREAM_ID_ANY for any stream. - * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream - * on DMA1. - * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream - * on DMA2. - * . - * @param[in] priority IRQ priority for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_dma_stream_t - * structure. - * @retval NULL if a/the stream is not available. - * - * @iclass - */ -const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - uint32_t i, startid, endid; - - osalDbgCheckClassI(); - - if (id < STM32_DMA_STREAMS) { - startid = id; - endid = id; - } -#if STM32_DMA_SUPPORTS_DMAMUX == TRUE - else if (id == STM32_DMA_STREAM_ID_ANY) { - startid = 0U; - endid = STM32_DMA_STREAMS - 1U; - } - else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) { - startid = 0U; - endid = STM32_DMA1_NUM_CHANNELS - 1U; - } -#if STM32_DMA2_NUM_CHANNELS > 0 - else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) { - startid = STM32_DMA1_NUM_CHANNELS; - endid = STM32_DMA_STREAMS - 1U; - } -#endif -#endif - else { - osalDbgCheck(false); - return NULL; - } - - for (i = startid; i <= endid; i++) { - uint32_t mask = (1U << i); - if ((dma.allocated_mask & mask) == 0U) { - const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i); - - /* Installs the DMA handler.*/ - dma.streams[i].func = func; - dma.streams[i].param = param; - dma.allocated_mask |= mask; - - /* Enabling DMA clocks required by the current streams set.*/ - if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) { - rccEnableDMA1(true); - } -#if STM32_DMA2_NUM_CHANNELS > 0 - if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) { - rccEnableDMA2(true); - } -#endif - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX) - /* Enabling DMAMUX if present.*/ - if (dma.allocated_mask != 0U) { - rccEnableDMAMUX(true); - } -#endif - - /* Enables the associated IRQ vector if not already enabled and if a - callback is defined.*/ - if (func != NULL) { - if ((dma.isr_mask & dmastp->cmask) == 0U) { - nvicEnableVector(dmastp->vector, priority); - } - dma.isr_mask |= mask; - } - - /* Putting the stream in a known state.*/ - dmaStreamDisable(dmastp); - dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; - - return dmastp; - } - } - - return NULL; -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific stream or: - * - @p STM32_DMA_STREAM_ID_ANY for any stream. - * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream - * on DMA1. - * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream - * on DMA2. - * . - * @param[in] priority IRQ priority for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_dma_stream_t - * structure. - * @retval NULL if a/the stream is not available. - * - * @api - */ -const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - const stm32_dma_stream_t *dmastp; - - osalSysLock(); - dmastp = dmaStreamAllocI(id, priority, func, param); - osalSysUnlock(); - - return dmastp; -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @iclass - */ -void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) { - uint32_t selfindex = (uint32_t)dmastp->selfindex; - - osalDbgCheck(dmastp != NULL); - - /* Check if the streams is not taken.*/ - osalDbgAssert((dma.allocated_mask & (1 << selfindex)) != 0U, - "not allocated"); - - /* Marks the stream as not allocated.*/ - dma.allocated_mask &= ~(1U << selfindex); - dma.isr_mask &= ~(1U << selfindex); - - /* Disables the associated IRQ vector if it is no more in use.*/ - if ((dma.isr_mask & dmastp->cmask) == 0U) { - nvicDisableVector(dmastp->vector); - } - - /* Removes the DMA handler.*/ - dma.streams[selfindex].func = NULL; - dma.streams[selfindex].param = NULL; - - /* Shutting down clocks that are no more required, if any.*/ - if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) { - rccDisableDMA1(); - } -#if STM32_DMA2_NUM_CHANNELS > 0 - if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) { - rccDisableDMA2(); - } -#endif - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX) - /* Shutting down DMAMUX if present.*/ - if (dma.allocated_mask == 0U) { - rccDisableDMAMUX(); - } -#endif -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @api - */ -void dmaStreamFree(const stm32_dma_stream_t *dmastp) { - - osalSysLock(); - dmaStreamFreeI(dmastp); - osalSysUnlock(); -} - -/** - * @brief Serves a DMA IRQ. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -void dmaServeInterrupt(const stm32_dma_stream_t *dmastp) { - uint32_t flags; - uint32_t selfindex = (uint32_t)dmastp->selfindex; - - flags = (dmastp->dma->ISR >> dmastp->shift) & STM32_DMA_ISR_MASK; - if (flags & dmastp->channel->CCR) { - dmastp->dma->IFCR = flags << dmastp->shift; - if (dma.streams[selfindex].func) { - dma.streams[selfindex].func(dma.streams[selfindex].param, flags); - } - } -} - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) -/** - * @brief Associates a peripheral request to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure - * @param[in] per peripheral identifier - * - * @special - */ -void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) { - - osalDbgCheck(per < 256U); - - dmastp->mux->CCR = per; -} -#endif - -#endif /* STM32_DMA_REQUIRED */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file DMAv1/stm32_dma.c + * @brief DMA helper driver code. + * + * @addtogroup STM32_DMA + * @details DMA sharing helper driver. In the STM32 the DMA streams are a + * shared resource, this driver allows to allocate and free DMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The DMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating streams. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring DMA services + has been enabled.*/ +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the DMA1 streams in @p dma_streams_mask. + */ +#define STM32_DMA1_STREAMS_MASK ((1U << STM32_DMA1_NUM_CHANNELS) - 1U) + +/** + * @brief Mask of the DMA2 streams in @p dma_streams_mask. + */ +#define STM32_DMA2_STREAMS_MASK (((1U << STM32_DMA2_NUM_CHANNELS) - \ + 1U) << STM32_DMA1_NUM_CHANNELS) + +#if STM32_DMA_SUPPORTS_CSELR == TRUE + +#if defined(DMA1_CSELR) +#define __DMA1_CSELR &DMA1_CSELR->CSELR +#else +#define __DMA1_CSELR &DMA1->CSELR +#endif + +#if defined(DMA2_CSELR) +#define __DMA2_CSELR &DMA2_CSELR->CSELR +#else +#define __DMA2_CSELR &DMA2->CSELR +#endif + +#define DMA1_CH1_VARIANT __DMA1_CSELR +#define DMA1_CH2_VARIANT __DMA1_CSELR +#define DMA1_CH3_VARIANT __DMA1_CSELR +#define DMA1_CH4_VARIANT __DMA1_CSELR +#define DMA1_CH5_VARIANT __DMA1_CSELR +#define DMA1_CH6_VARIANT __DMA1_CSELR +#define DMA1_CH7_VARIANT __DMA1_CSELR +#define DMA1_CH8_VARIANT __DMA1_CSELR +#define DMA2_CH1_VARIANT __DMA2_CSELR +#define DMA2_CH2_VARIANT __DMA2_CSELR +#define DMA2_CH3_VARIANT __DMA2_CSELR +#define DMA2_CH4_VARIANT __DMA2_CSELR +#define DMA2_CH5_VARIANT __DMA2_CSELR +#define DMA2_CH6_VARIANT __DMA2_CSELR +#define DMA2_CH7_VARIANT __DMA2_CSELR +#define DMA2_CH8_VARIANT __DMA2_CSELR + +#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE + +#define DMAMUX1_CHANNEL(id) (DMAMUX1_BASE + ((id) * 4U)) + +#define DMA1_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0)) +#define DMA1_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1)) +#define DMA1_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2)) +#define DMA1_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3)) +#define DMA1_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4)) +#define DMA1_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5)) +#define DMA1_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6)) +#define DMA1_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7)) +#define DMA2_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6 + STM32_DMA1_NUM_CHANNELS)) +#define DMA2_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7 + STM32_DMA1_NUM_CHANNELS)) + +#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ + +#define DMA1_CH1_VARIANT 0 +#define DMA1_CH2_VARIANT 0 +#define DMA1_CH3_VARIANT 0 +#define DMA1_CH4_VARIANT 0 +#define DMA1_CH5_VARIANT 0 +#define DMA1_CH6_VARIANT 0 +#define DMA1_CH7_VARIANT 0 +#define DMA2_CH1_VARIANT 0 +#define DMA2_CH2_VARIANT 0 +#define DMA2_CH3_VARIANT 0 +#define DMA2_CH4_VARIANT 0 +#define DMA2_CH5_VARIANT 0 +#define DMA2_CH6_VARIANT 0 +#define DMA2_CH7_VARIANT 0 + +#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ + +/* + * Default ISR collision masks. + */ +#if !defined(STM32_DMA1_CH1_CMASK) +#define STM32_DMA1_CH1_CMASK (1U << 0U) +#endif + +#if !defined(STM32_DMA1_CH2_CMASK) +#define STM32_DMA1_CH2_CMASK (1U << 1U) +#endif + +#if !defined(STM32_DMA1_CH3_CMASK) +#define STM32_DMA1_CH3_CMASK (1U << 2U) +#endif + +#if !defined(STM32_DMA1_CH4_CMASK) +#define STM32_DMA1_CH4_CMASK (1U << 3U) +#endif + +#if !defined(STM32_DMA1_CH5_CMASK) +#define STM32_DMA1_CH5_CMASK (1U << 4U) +#endif + +#if !defined(STM32_DMA1_CH6_CMASK) +#define STM32_DMA1_CH6_CMASK (1U << 5U) +#endif + +#if !defined(STM32_DMA1_CH7_CMASK) +#define STM32_DMA1_CH7_CMASK (1U << 6U) +#endif + +#if !defined(STM32_DMA1_CH8_CMASK) +#define STM32_DMA1_CH8_CMASK (1U << 7U) +#endif + +#if !defined(STM32_DMA2_CH1_CMASK) +#define STM32_DMA2_CH1_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 0U)) +#endif + +#if !defined(STM32_DMA2_CH2_CMASK) +#define STM32_DMA2_CH2_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 1U)) +#endif + +#if !defined(STM32_DMA2_CH3_CMASK) +#define STM32_DMA2_CH3_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 2U)) +#endif + +#if !defined(STM32_DMA2_CH4_CMASK) +#define STM32_DMA2_CH4_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 3U)) +#endif + +#if !defined(STM32_DMA2_CH5_CMASK) +#define STM32_DMA2_CH5_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 4U)) +#endif + +#if !defined(STM32_DMA2_CH6_CMASK) +#define STM32_DMA2_CH6_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 5U)) +#endif + +#if !defined(STM32_DMA2_CH7_CMASK) +#define STM32_DMA2_CH7_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 6U)) +#endif + +#if !defined(STM32_DMA2_CH8_CMASK) +#define STM32_DMA2_CH8_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 7U)) +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief DMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. + */ +const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { +#if STM32_DMA1_NUM_CHANNELS > 0 + {DMA1, DMA1_Channel1, STM32_DMA1_CH1_CMASK, DMA1_CH1_VARIANT, 0, 0, STM32_DMA1_CH1_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 1 + {DMA1, DMA1_Channel2, STM32_DMA1_CH2_CMASK, DMA1_CH2_VARIANT, 4, 1, STM32_DMA1_CH2_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 2 + {DMA1, DMA1_Channel3, STM32_DMA1_CH3_CMASK, DMA1_CH3_VARIANT, 8, 2, STM32_DMA1_CH3_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 3 + {DMA1, DMA1_Channel4, STM32_DMA1_CH4_CMASK, DMA1_CH4_VARIANT, 12, 3, STM32_DMA1_CH4_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 4 + {DMA1, DMA1_Channel5, STM32_DMA1_CH5_CMASK, DMA1_CH5_VARIANT, 16, 4, STM32_DMA1_CH5_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 5 + {DMA1, DMA1_Channel6, STM32_DMA1_CH6_CMASK, DMA1_CH6_VARIANT, 20, 5, STM32_DMA1_CH6_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 6 + {DMA1, DMA1_Channel7, STM32_DMA1_CH7_CMASK, DMA1_CH7_VARIANT, 24, 6, STM32_DMA1_CH7_NUMBER}, +#endif +#if STM32_DMA1_NUM_CHANNELS > 7 + {DMA1, DMA1_Channel8, STM32_DMA1_CH8_CMASK, DMA1_CH8_VARIANT, 28, 7, STM32_DMA1_CH8_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 0 + {DMA2, DMA2_Channel1, STM32_DMA2_CH1_CMASK, DMA2_CH1_VARIANT, 0, 0 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH1_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 1 + {DMA2, DMA2_Channel2, STM32_DMA2_CH2_CMASK, DMA2_CH2_VARIANT, 4, 1 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH2_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 2 + {DMA2, DMA2_Channel3, STM32_DMA2_CH3_CMASK, DMA2_CH3_VARIANT, 8, 2 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH3_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 3 + {DMA2, DMA2_Channel4, STM32_DMA2_CH4_CMASK, DMA2_CH4_VARIANT, 12, 3 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH4_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 4 + {DMA2, DMA2_Channel5, STM32_DMA2_CH5_CMASK, DMA2_CH5_VARIANT, 16, 4 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH5_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 5 + {DMA2, DMA2_Channel6, STM32_DMA2_CH6_CMASK, DMA2_CH6_VARIANT, 20, 5 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH6_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 6 + {DMA2, DMA2_Channel7, STM32_DMA2_CH7_CMASK, DMA2_CH7_VARIANT, 24, 6 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH7_NUMBER}, +#endif +#if STM32_DMA2_NUM_CHANNELS > 7 + {DMA2, DMA2_Channel8, STM32_DMA2_CH8_CMASK, DMA2_CH8_VARIANT, 28, 7 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH8_NUMBER}, +#endif +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Global DMA-related data structures. + */ +static struct { + /** + * @brief Mask of the allocated streams. + */ + uint32_t allocated_mask; + /** + * @brief Mask of the enabled streams ISRs. + */ + uint32_t isr_mask; + /** + * @brief DMA IRQ redirectors. + */ + struct { + /** + * @brief DMA callback function. + */ + stm32_dmaisr_t func; + /** + * @brief DMA callback parameter. + */ + void *param; + } streams[STM32_DMA_STREAMS]; +} dma; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if defined(STM32_DMA1_CH1_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 1 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH2_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 2 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH3_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 3 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH4_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 4 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH5_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 5 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM5); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH6_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 6 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM6); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH7_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 7 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM7); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA1_CH8_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 stream 8 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA1_STREAM8); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH1_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 1 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH2_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 2 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH3_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 3 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH4_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 4 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH5_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 5 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM5); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH6_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 6 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM6); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH7_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 7 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM7); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if defined(STM32_DMA2_CH8_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 stream 8 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + dmaServeInterrupt(STM32_DMA2_STREAM8); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA helper initialization. + * + * @init + */ +void dmaInit(void) { + int i; + + dma.allocated_mask = 0U; + dma.isr_mask = 0U; + for (i = 0; i < STM32_DMA_STREAMS; i++) { + _stm32_dma_streams[i].channel->CCR = STM32_DMA_CCR_RESET_VALUE; + dma.streams[i].func = NULL; + } + DMA1->IFCR = 0xFFFFFFFFU; +#if STM32_DMA2_NUM_CHANNELS > 0 + DMA2->IFCR = 0xFFFFFFFFU; +#endif +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific stream or: + * - @p STM32_DMA_STREAM_ID_ANY for any stream. + * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream + * on DMA1. + * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream + * on DMA2. + * . + * @param[in] priority IRQ priority for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_dma_stream_t + * structure. + * @retval NULL if a/the stream is not available. + * + * @iclass + */ +const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + uint32_t i, startid, endid; + + osalDbgCheckClassI(); + + if (id < STM32_DMA_STREAMS) { + startid = id; + endid = id; + } +#if STM32_DMA_SUPPORTS_DMAMUX == TRUE + else if (id == STM32_DMA_STREAM_ID_ANY) { + startid = 0U; + endid = STM32_DMA_STREAMS - 1U; + } + else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) { + startid = 0U; + endid = STM32_DMA1_NUM_CHANNELS - 1U; + } +#if STM32_DMA2_NUM_CHANNELS > 0 + else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) { + startid = STM32_DMA1_NUM_CHANNELS; + endid = STM32_DMA_STREAMS - 1U; + } +#endif +#endif + else { + osalDbgCheck(false); + return NULL; + } + + for (i = startid; i <= endid; i++) { + uint32_t mask = (1U << i); + if ((dma.allocated_mask & mask) == 0U) { + const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i); + + /* Installs the DMA handler.*/ + dma.streams[i].func = func; + dma.streams[i].param = param; + dma.allocated_mask |= mask; + + /* Enabling DMA clocks required by the current streams set.*/ + if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) { + rccEnableDMA1(true); + } +#if STM32_DMA2_NUM_CHANNELS > 0 + if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) { + rccEnableDMA2(true); + } +#endif + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX) + /* Enabling DMAMUX if present.*/ + if (dma.allocated_mask != 0U) { + rccEnableDMAMUX(true); + } +#endif + + /* Enables the associated IRQ vector if not already enabled and if a + callback is defined.*/ + if (func != NULL) { + if ((dma.isr_mask & dmastp->cmask) == 0U) { + nvicEnableVector(dmastp->vector, priority); + } + dma.isr_mask |= mask; + } + + /* Putting the stream in a known state.*/ + dmaStreamDisable(dmastp); + dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; + + return dmastp; + } + } + + return NULL; +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific stream or: + * - @p STM32_DMA_STREAM_ID_ANY for any stream. + * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream + * on DMA1. + * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream + * on DMA2. + * . + * @param[in] priority IRQ priority for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_dma_stream_t + * structure. + * @retval NULL if a/the stream is not available. + * + * @api + */ +const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + const stm32_dma_stream_t *dmastp; + + osalSysLock(); + dmastp = dmaStreamAllocI(id, priority, func, param); + osalSysUnlock(); + + return dmastp; +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @iclass + */ +void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) { + uint32_t selfindex = (uint32_t)dmastp->selfindex; + + osalDbgCheck(dmastp != NULL); + + /* Check if the streams is not taken.*/ + osalDbgAssert((dma.allocated_mask & (1 << selfindex)) != 0U, + "not allocated"); + + /* Marks the stream as not allocated.*/ + dma.allocated_mask &= ~(1U << selfindex); + dma.isr_mask &= ~(1U << selfindex); + + /* Disables the associated IRQ vector if it is no more in use.*/ + if ((dma.isr_mask & dmastp->cmask) == 0U) { + nvicDisableVector(dmastp->vector); + } + + /* Removes the DMA handler.*/ + dma.streams[selfindex].func = NULL; + dma.streams[selfindex].param = NULL; + + /* Shutting down clocks that are no more required, if any.*/ + if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) { + rccDisableDMA1(); + } +#if STM32_DMA2_NUM_CHANNELS > 0 + if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) { + rccDisableDMA2(); + } +#endif + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX) + /* Shutting down DMAMUX if present.*/ + if (dma.allocated_mask == 0U) { + rccDisableDMAMUX(); + } +#endif +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @api + */ +void dmaStreamFree(const stm32_dma_stream_t *dmastp) { + + osalSysLock(); + dmaStreamFreeI(dmastp); + osalSysUnlock(); +} + +/** + * @brief Serves a DMA IRQ. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +void dmaServeInterrupt(const stm32_dma_stream_t *dmastp) { + uint32_t flags; + uint32_t selfindex = (uint32_t)dmastp->selfindex; + + flags = (dmastp->dma->ISR >> dmastp->shift) & STM32_DMA_ISR_MASK; + if (flags & dmastp->channel->CCR) { + dmastp->dma->IFCR = flags << dmastp->shift; + if (dma.streams[selfindex].func) { + dma.streams[selfindex].func(dma.streams[selfindex].param, flags); + } + } +} + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) +/** + * @brief Associates a peripheral request to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure + * @param[in] per peripheral identifier + * + * @special + */ +void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) { + + osalDbgCheck(per < 256U); + + dmastp->mux->CCR = per; +} +#endif + +#endif /* STM32_DMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h index 54b6bde846..a91f5cb5e7 100644 --- a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h +++ b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h @@ -1,554 +1,554 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file DMAv1/stm32_dma.h - * @brief DMA helper driver header. - * @note This driver uses the new naming convention used for the STM32F2xx - * so the "DMA channels" are referred as "DMA streams". - * - * @addtogroup STM32_DMA - * @{ - */ - -#ifndef STM32_DMA_H -#define STM32_DMA_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief DMA capability. - * @details if @p TRUE then the DMA is able of burst transfers, FIFOs, - * scatter gather and other advanced features. - */ -#define STM32_DMA_ADVANCED FALSE - -/** - * @brief Total number of DMA streams. - * @details This is the total number of streams among all the DMA units. - */ -#define STM32_DMA_STREAMS (STM32_DMA1_NUM_CHANNELS + \ - STM32_DMA2_NUM_CHANNELS) - -/** - * @brief Mask of the ISR bits passed to the DMA callback functions. - */ -#define STM32_DMA_ISR_MASK 0x0E - -/** - * @brief Returns the request line associated to the specified stream. - * @note In some STM32 manuals the request line is named confusingly - * channel. - * - * @param[in] id the unique numeric stream identifier - * @param[in] c a stream/request association word, one request per - * nibble - * @return Returns the request associated to the stream. - */ -#define STM32_DMA_GETCHANNEL(id, c) \ - (((uint32_t)(c) >> (((uint32_t)(id) % (uint32_t)STM32_DMA1_NUM_CHANNELS) * 4U)) & 15U) - -/** - * @brief Checks if a DMA priority is within the valid range. - * @param[in] prio DMA priority - * - * @retval The check result. - * @retval false invalid DMA priority. - * @retval true correct DMA priority. - */ -#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) - -#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__) -/** - * @brief Checks if a DMA stream id is within the valid range. - * - * @param[in] id DMA stream id - * @retval The check result. - * @retval false invalid DMA channel. - * @retval true correct DMA channel. - */ -#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) < STM32_DMA_STREAMS)) -#else /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ -#if STM32_DMA2_NUM_CHANNELS > 0 -#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) <= (STM32_DMA_STREAMS + 2))) -#else -#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) <= (STM32_DMA_STREAMS + 1))) -#endif -#endif /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ - -/** - * @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) * STM32_DMA1_NUM_CHANNELS) + ((stream) - 1)) - -/** - * @brief Returns a DMA stream identifier mask. - * - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return A DMA stream identifier mask. - */ -#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ - (1U << 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) (((1U << (id)) & (mask))) - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__) -/** - * @name Special stream identifiers - * @{ - */ -#define STM32_DMA_STREAM_ID_ANY STM32_DMA_STREAMS -#define STM32_DMA_STREAM_ID_ANY_DMA1 (STM32_DMA_STREAM_ID_ANY + 1) -#if STM32_DMA2_NUM_CHANNELS > 0 -#define STM32_DMA_STREAM_ID_ANY_DMA2 (STM32_DMA_STREAM_ID_ANY_DMA1 + 1) -#endif -/** @} */ -#endif - -/** - * @name DMA streams identifiers - * @{ - */ -/** - * @brief Returns a pointer to a stm32_dma_stream_t structure. - * - * @param[in] id the stream numeric identifier - * @return A pointer to the stm32_dma_stream_t constant structure - * associated to the DMA stream. - */ -#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) - -#if STM32_DMA1_NUM_CHANNELS > 0 -#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0) -#endif -#if STM32_DMA1_NUM_CHANNELS > 1 -#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1) -#endif -#if STM32_DMA1_NUM_CHANNELS > 2 -#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2) -#endif -#if STM32_DMA1_NUM_CHANNELS > 3 -#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3) -#endif -#if STM32_DMA1_NUM_CHANNELS > 4 -#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4) -#endif -#if STM32_DMA1_NUM_CHANNELS > 5 -#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(5) -#endif -#if STM32_DMA1_NUM_CHANNELS > 6 -#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(6) -#endif -#if STM32_DMA1_NUM_CHANNELS > 7 -#define STM32_DMA1_STREAM8 STM32_DMA_STREAM(7) -#endif -#if STM32_DMA2_NUM_CHANNELS > 0 -#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 0) -#endif -#if STM32_DMA2_NUM_CHANNELS > 1 -#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 1) -#endif -#if STM32_DMA2_NUM_CHANNELS > 2 -#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 2) -#endif -#if STM32_DMA2_NUM_CHANNELS > 3 -#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 3) -#endif -#if STM32_DMA2_NUM_CHANNELS > 4 -#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 4) -#endif -#if STM32_DMA2_NUM_CHANNELS > 5 -#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 5) -#endif -#if STM32_DMA2_NUM_CHANNELS > 6 -#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 6) -#endif -#if STM32_DMA2_NUM_CHANNELS > 7 -#define STM32_DMA2_STREAM8 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 7) -#endif -/** @} */ - -/** - * @name CR register constants common to all DMA types - * @{ - */ -#define STM32_DMA_CCR_RESET_VALUE 0x00000000U -#define STM32_DMA_CR_EN DMA_CCR_EN -#define STM32_DMA_CR_TEIE DMA_CCR_TEIE -#define STM32_DMA_CR_HTIE DMA_CCR_HTIE -#define STM32_DMA_CR_TCIE DMA_CCR_TCIE -#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM) -#define STM32_DMA_CR_DIR_P2M 0U -#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR -#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM -#define STM32_DMA_CR_CIRC DMA_CCR_CIRC -#define STM32_DMA_CR_PINC DMA_CCR_PINC -#define STM32_DMA_CR_MINC DMA_CCR_MINC -#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE -#define STM32_DMA_CR_PSIZE_BYTE 0U -#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0 -#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1 -#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE -#define STM32_DMA_CR_MSIZE_BYTE 0U -#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0 -#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1 -#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ - STM32_DMA_CR_MSIZE_MASK) -#define STM32_DMA_CR_PL_MASK DMA_CCR_PL -#define STM32_DMA_CR_PL(n) ((n) << 12U) -/** @} */ - -/** - * @name Request line selector macro - * @{ - */ -#if STM32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__) -#define STM32_DMA_CR_CHSEL_MASK (15U << 16U) -#define STM32_DMA_CR_CHSEL(n) ((n) << 16U) -#else -#define STM32_DMA_CR_CHSEL_MASK 0U -#define STM32_DMA_CR_CHSEL(n) 0U -#endif -/** @} */ - -/** - * @name CR register constants only found in enhanced DMA - * @{ - */ -#define STM32_DMA_CR_DMEIE 0U /**< @brief Ignored by normal DMA. */ -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - * @{ - */ -#define STM32_DMA_ISR_FEIF 0U -#define STM32_DMA_ISR_DMEIF 0U -#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 -#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 -#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_DMA_SUPPORTS_DMAMUX) -#error "STM32_DMA_SUPPORTS_DMAMUX not defined in registry" -#endif - -#if !defined(STM32_DMA_SUPPORTS_CSELR) -#error "STM32_DMA_SUPPORTS_CSELR not defined in registry" -#endif - -#if STM32_DMA_SUPPORTS_DMAMUX && STM32_DMA_SUPPORTS_CSELR -#error "STM32_DMA_SUPPORTS_DMAMUX and STM32_DMA_SUPPORTS_CSELR both TRUE" -#endif - -#if !defined(STM32_DMA1_NUM_CHANNELS) -#error "STM32_DMA1_NUM_CHANNELS not defined in registry" -#endif - -#if !defined(STM32_DMA2_NUM_CHANNELS) -#error "STM32_DMA2_NUM_CHANNELS not defined in registry" -#endif - -#if (STM32_DMA1_NUM_CHANNELS < 0) || (STM32_DMA1_NUM_CHANNELS > 8) -#error "unsupported channels configuration" -#endif - -#if (STM32_DMA2_NUM_CHANNELS < 0) || (STM32_DMA2_NUM_CHANNELS > 8) -#error "unsupported channels configuration" -#endif - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) -#include "stm32_dmamux.h" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a DMA callback. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the ISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); - -/** - * @brief STM32 DMA stream descriptor structure. - */ -typedef struct { - DMA_TypeDef *dma; /**< @brief Associated DMA. */ - DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ - uint32_t cmask; /**< @brief Mask of streams sharing - the same ISR. */ -#if (STM32_DMA_SUPPORTS_CSELR == TRUE) || defined(__DOXYGEN__) - volatile uint32_t *cselr; /**< @brief Associated CSELR reg. */ -#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE - DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */ -#else - uint8_t dummy; /**< @brief Filler. */ -#endif - uint8_t shift; /**< @brief Bit offset in ISR, IFCR - and CSELR registers. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_dma_stream_t; - -/*===========================================================================*/ -/* 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 dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CPAR register - * - * @special - */ -#define dmaStreamSetPeripheral(dmastp, addr) { \ - (dmastp)->channel->CPAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CMAR register - * - * @special - */ -#define dmaStreamSetMemory0(dmastp, addr) { \ - (dmastp)->channel->CMAR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define dmaStreamSetTransactionSize(dmastp, size) { \ - (dmastp)->channel->CNDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register - * - * @special - */ -#if STM32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__) -#define dmaStreamSetMode(dmastp, mode) { \ - uint32_t cselr = *(dmastp)->cselr; \ - cselr &= ~(0x0000000FU << (dmastp)->shift); \ - cselr |= (((uint32_t)(mode) >> 16U) << (dmastp)->shift); \ - *(dmastp)->cselr = cselr; \ - (dmastp)->channel->CCR = (uint32_t)(mode); \ -} -#else -#define dmaStreamSetMode(dmastp, mode) { \ - (dmastp)->channel->CCR = (uint32_t)(mode); \ -} -#endif - -/** - * @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 dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamEnable(dmastp) { \ - (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream disable. - * @details The function disables the specified stream and then clears any - * pending interrupt. - * @note This function can be invoked in both ISR or thread context. - * @note Interrupts enabling flags are set to zero after this call, see - * bug 3607518. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamDisable(dmastp) { \ - (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \ - dmaStreamClearInterrupt(dmastp); \ -} - -/** - * @brief DMA stream interrupt sources clear. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamClearInterrupt(dmastp) { \ - (dmastp)->dma->IFCR = STM32_DMA_ISR_MASK << (dmastp)->shift; \ -} - -/** - * @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 dmaStreamAlloc(). - * @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 dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - */ -#define dmaWaitCompletion(dmastp) { \ - while ((dmastp)->channel->CNDTR > 0U) \ - ; \ - dmaStreamDisable(dmastp); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dmaInit(void); - const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - void dmaStreamFreeI(const stm32_dma_stream_t *dmastp); - void dmaStreamFree(const stm32_dma_stream_t *dmastp); - void dmaServeInterrupt(const stm32_dma_stream_t *dmastp); -#if STM32_DMA_SUPPORTS_DMAMUX == TRUE - void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMA_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file DMAv1/stm32_dma.h + * @brief DMA helper driver header. + * @note This driver uses the new naming convention used for the STM32F2xx + * so the "DMA channels" are referred as "DMA streams". + * + * @addtogroup STM32_DMA + * @{ + */ + +#ifndef STM32_DMA_H +#define STM32_DMA_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief DMA capability. + * @details if @p TRUE then the DMA is able of burst transfers, FIFOs, + * scatter gather and other advanced features. + */ +#define STM32_DMA_ADVANCED FALSE + +/** + * @brief Total number of DMA streams. + * @details This is the total number of streams among all the DMA units. + */ +#define STM32_DMA_STREAMS (STM32_DMA1_NUM_CHANNELS + \ + STM32_DMA2_NUM_CHANNELS) + +/** + * @brief Mask of the ISR bits passed to the DMA callback functions. + */ +#define STM32_DMA_ISR_MASK 0x0E + +/** + * @brief Returns the request line associated to the specified stream. + * @note In some STM32 manuals the request line is named confusingly + * channel. + * + * @param[in] id the unique numeric stream identifier + * @param[in] c a stream/request association word, one request per + * nibble + * @return Returns the request associated to the stream. + */ +#define STM32_DMA_GETCHANNEL(id, c) \ + (((uint32_t)(c) >> (((uint32_t)(id) % (uint32_t)STM32_DMA1_NUM_CHANNELS) * 4U)) & 15U) + +/** + * @brief Checks if a DMA priority is within the valid range. + * @param[in] prio DMA priority + * + * @retval The check result. + * @retval false invalid DMA priority. + * @retval true correct DMA priority. + */ +#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) + +#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__) +/** + * @brief Checks if a DMA stream id is within the valid range. + * + * @param[in] id DMA stream id + * @retval The check result. + * @retval false invalid DMA channel. + * @retval true correct DMA channel. + */ +#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) < STM32_DMA_STREAMS)) +#else /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ +#if STM32_DMA2_NUM_CHANNELS > 0 +#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) <= (STM32_DMA_STREAMS + 2))) +#else +#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) <= (STM32_DMA_STREAMS + 1))) +#endif +#endif /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ + +/** + * @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) * STM32_DMA1_NUM_CHANNELS) + ((stream) - 1)) + +/** + * @brief Returns a DMA stream identifier mask. + * + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return A DMA stream identifier mask. + */ +#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ + (1U << 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) (((1U << (id)) & (mask))) + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__) +/** + * @name Special stream identifiers + * @{ + */ +#define STM32_DMA_STREAM_ID_ANY STM32_DMA_STREAMS +#define STM32_DMA_STREAM_ID_ANY_DMA1 (STM32_DMA_STREAM_ID_ANY + 1) +#if STM32_DMA2_NUM_CHANNELS > 0 +#define STM32_DMA_STREAM_ID_ANY_DMA2 (STM32_DMA_STREAM_ID_ANY_DMA1 + 1) +#endif +/** @} */ +#endif + +/** + * @name DMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_dma_stream_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_dma_stream_t constant structure + * associated to the DMA stream. + */ +#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) + +#if STM32_DMA1_NUM_CHANNELS > 0 +#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0) +#endif +#if STM32_DMA1_NUM_CHANNELS > 1 +#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1) +#endif +#if STM32_DMA1_NUM_CHANNELS > 2 +#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2) +#endif +#if STM32_DMA1_NUM_CHANNELS > 3 +#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3) +#endif +#if STM32_DMA1_NUM_CHANNELS > 4 +#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4) +#endif +#if STM32_DMA1_NUM_CHANNELS > 5 +#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(5) +#endif +#if STM32_DMA1_NUM_CHANNELS > 6 +#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(6) +#endif +#if STM32_DMA1_NUM_CHANNELS > 7 +#define STM32_DMA1_STREAM8 STM32_DMA_STREAM(7) +#endif +#if STM32_DMA2_NUM_CHANNELS > 0 +#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 0) +#endif +#if STM32_DMA2_NUM_CHANNELS > 1 +#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 1) +#endif +#if STM32_DMA2_NUM_CHANNELS > 2 +#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 2) +#endif +#if STM32_DMA2_NUM_CHANNELS > 3 +#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 3) +#endif +#if STM32_DMA2_NUM_CHANNELS > 4 +#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 4) +#endif +#if STM32_DMA2_NUM_CHANNELS > 5 +#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 5) +#endif +#if STM32_DMA2_NUM_CHANNELS > 6 +#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 6) +#endif +#if STM32_DMA2_NUM_CHANNELS > 7 +#define STM32_DMA2_STREAM8 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 7) +#endif +/** @} */ + +/** + * @name CR register constants common to all DMA types + * @{ + */ +#define STM32_DMA_CCR_RESET_VALUE 0x00000000U +#define STM32_DMA_CR_EN DMA_CCR_EN +#define STM32_DMA_CR_TEIE DMA_CCR_TEIE +#define STM32_DMA_CR_HTIE DMA_CCR_HTIE +#define STM32_DMA_CR_TCIE DMA_CCR_TCIE +#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM) +#define STM32_DMA_CR_DIR_P2M 0U +#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR +#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM +#define STM32_DMA_CR_CIRC DMA_CCR_CIRC +#define STM32_DMA_CR_PINC DMA_CCR_PINC +#define STM32_DMA_CR_MINC DMA_CCR_MINC +#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE +#define STM32_DMA_CR_PSIZE_BYTE 0U +#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0 +#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1 +#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE +#define STM32_DMA_CR_MSIZE_BYTE 0U +#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0 +#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1 +#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ + STM32_DMA_CR_MSIZE_MASK) +#define STM32_DMA_CR_PL_MASK DMA_CCR_PL +#define STM32_DMA_CR_PL(n) ((n) << 12U) +/** @} */ + +/** + * @name Request line selector macro + * @{ + */ +#if STM32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__) +#define STM32_DMA_CR_CHSEL_MASK (15U << 16U) +#define STM32_DMA_CR_CHSEL(n) ((n) << 16U) +#else +#define STM32_DMA_CR_CHSEL_MASK 0U +#define STM32_DMA_CR_CHSEL(n) 0U +#endif +/** @} */ + +/** + * @name CR register constants only found in enhanced DMA + * @{ + */ +#define STM32_DMA_CR_DMEIE 0U /**< @brief Ignored by normal DMA. */ +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + * @{ + */ +#define STM32_DMA_ISR_FEIF 0U +#define STM32_DMA_ISR_DMEIF 0U +#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 +#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 +#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_DMA_SUPPORTS_DMAMUX) +#error "STM32_DMA_SUPPORTS_DMAMUX not defined in registry" +#endif + +#if !defined(STM32_DMA_SUPPORTS_CSELR) +#error "STM32_DMA_SUPPORTS_CSELR not defined in registry" +#endif + +#if STM32_DMA_SUPPORTS_DMAMUX && STM32_DMA_SUPPORTS_CSELR +#error "STM32_DMA_SUPPORTS_DMAMUX and STM32_DMA_SUPPORTS_CSELR both TRUE" +#endif + +#if !defined(STM32_DMA1_NUM_CHANNELS) +#error "STM32_DMA1_NUM_CHANNELS not defined in registry" +#endif + +#if !defined(STM32_DMA2_NUM_CHANNELS) +#error "STM32_DMA2_NUM_CHANNELS not defined in registry" +#endif + +#if (STM32_DMA1_NUM_CHANNELS < 0) || (STM32_DMA1_NUM_CHANNELS > 8) +#error "unsupported channels configuration" +#endif + +#if (STM32_DMA2_NUM_CHANNELS < 0) || (STM32_DMA2_NUM_CHANNELS > 8) +#error "unsupported channels configuration" +#endif + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) +#include "stm32_dmamux.h" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a DMA callback. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the ISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); + +/** + * @brief STM32 DMA stream descriptor structure. + */ +typedef struct { + DMA_TypeDef *dma; /**< @brief Associated DMA. */ + DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ + uint32_t cmask; /**< @brief Mask of streams sharing + the same ISR. */ +#if (STM32_DMA_SUPPORTS_CSELR == TRUE) || defined(__DOXYGEN__) + volatile uint32_t *cselr; /**< @brief Associated CSELR reg. */ +#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE + DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */ +#else + uint8_t dummy; /**< @brief Filler. */ +#endif + uint8_t shift; /**< @brief Bit offset in ISR, IFCR + and CSELR registers. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_dma_stream_t; + +/*===========================================================================*/ +/* 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 dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CPAR register + * + * @special + */ +#define dmaStreamSetPeripheral(dmastp, addr) { \ + (dmastp)->channel->CPAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CMAR register + * + * @special + */ +#define dmaStreamSetMemory0(dmastp, addr) { \ + (dmastp)->channel->CMAR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define dmaStreamSetTransactionSize(dmastp, size) { \ + (dmastp)->channel->CNDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register + * + * @special + */ +#if STM32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__) +#define dmaStreamSetMode(dmastp, mode) { \ + uint32_t cselr = *(dmastp)->cselr; \ + cselr &= ~(0x0000000FU << (dmastp)->shift); \ + cselr |= (((uint32_t)(mode) >> 16U) << (dmastp)->shift); \ + *(dmastp)->cselr = cselr; \ + (dmastp)->channel->CCR = (uint32_t)(mode); \ +} +#else +#define dmaStreamSetMode(dmastp, mode) { \ + (dmastp)->channel->CCR = (uint32_t)(mode); \ +} +#endif + +/** + * @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 dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamEnable(dmastp) { \ + (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream disable. + * @details The function disables the specified stream and then clears any + * pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamDisable(dmastp) { \ + (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \ + dmaStreamClearInterrupt(dmastp); \ +} + +/** + * @brief DMA stream interrupt sources clear. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamClearInterrupt(dmastp) { \ + (dmastp)->dma->IFCR = STM32_DMA_ISR_MASK << (dmastp)->shift; \ +} + +/** + * @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 dmaStreamAlloc(). + * @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 dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + */ +#define dmaWaitCompletion(dmastp) { \ + while ((dmastp)->channel->CNDTR > 0U) \ + ; \ + dmaStreamDisable(dmastp); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dmaInit(void); + const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + void dmaStreamFreeI(const stm32_dma_stream_t *dmastp); + void dmaStreamFree(const stm32_dma_stream_t *dmastp); + void dmaServeInterrupt(const stm32_dma_stream_t *dmastp); +#if STM32_DMA_SUPPORTS_DMAMUX == TRUE + void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMA_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/DMAv2/driver.mk b/os/hal/ports/STM32/LLD/DMAv2/driver.mk index bdc468a280..0bc685374a 100644 --- a/os/hal/ports/STM32/LLD/DMAv2/driver.mk +++ b/os/hal/ports/STM32/LLD/DMAv2/driver.mk @@ -1,2 +1,2 @@ -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2 diff --git a/os/hal/ports/STM32/LLD/DMAv2/notes.txt b/os/hal/ports/STM32/LLD/DMAv2/notes.txt index 4c01d83091..aadcf2cb3a 100644 --- a/os/hal/ports/STM32/LLD/DMAv2/notes.txt +++ b/os/hal/ports/STM32/LLD/DMAv2/notes.txt @@ -1,18 +1,18 @@ -STM32 DMAv2 driver. - -Driver capability: - -- The driver supports the STM32 enhanced DMA controller found on F2, F4 and - F7 sub-families. -- Support for automatic the channel selection. -- Support for cache flushing and invalidation. - -The file registry must export: - -STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other - drivers use it to enable checks on DMA - channels. Probably will be removed in the - future. -STM32_HAS_DMAx - Support for DMA unit "x" (1..2). -STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7). -STM32_DMAn_CHx_NUMBER - Vector number for channel "n" (0..7). +STM32 DMAv2 driver. + +Driver capability: + +- The driver supports the STM32 enhanced DMA controller found on F2, F4 and + F7 sub-families. +- Support for automatic the channel selection. +- Support for cache flushing and invalidation. + +The file registry must export: + +STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other + drivers use it to enable checks on DMA + channels. Probably will be removed in the + future. +STM32_HAS_DMAx - Support for DMA unit "x" (1..2). +STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7). +STM32_DMAn_CHx_NUMBER - Vector number for channel "n" (0..7). diff --git a/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c b/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c index 10b4b68fe5..eab184a20f 100644 --- a/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c +++ b/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c @@ -1,675 +1,675 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file DMAv2/stm32_dma.c - * @brief Enhanced DMA helper driver code. - * - * @addtogroup STM32_DMA - * @details DMA sharing helper driver. In the STM32 the DMA streams are a - * shared resource, this driver allows to allocate and free DMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating streams. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring DMA services - has been enabled.*/ -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the DMA1 streams in @p dma.allocated_mask. - */ -#define STM32_DMA1_STREAMS_MASK 0x000000FFU - -/** - * @brief Mask of the DMA2 streams in @p dma.allocated_mask. - */ -#define STM32_DMA2_STREAMS_MASK 0x0000FF00U - -#if STM32_DMA_SUPPORTS_DMAMUX == TRUE - -#define DMA1_CH0_VARIANT DMAMUX1_Channel0 -#define DMA1_CH1_VARIANT DMAMUX1_Channel1 -#define DMA1_CH2_VARIANT DMAMUX1_Channel2 -#define DMA1_CH3_VARIANT DMAMUX1_Channel3 -#define DMA1_CH4_VARIANT DMAMUX1_Channel4 -#define DMA1_CH5_VARIANT DMAMUX1_Channel5 -#define DMA1_CH6_VARIANT DMAMUX1_Channel6 -#define DMA1_CH7_VARIANT DMAMUX1_Channel7 -#define DMA2_CH0_VARIANT DMAMUX1_Channel8 -#define DMA2_CH1_VARIANT DMAMUX1_Channel9 -#define DMA2_CH2_VARIANT DMAMUX1_Channel10 -#define DMA2_CH3_VARIANT DMAMUX1_Channel11 -#define DMA2_CH4_VARIANT DMAMUX1_Channel12 -#define DMA2_CH5_VARIANT DMAMUX1_Channel13 -#define DMA2_CH6_VARIANT DMAMUX1_Channel14 -#define DMA2_CH7_VARIANT DMAMUX1_Channel15 - -#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ - -#define DMA1_CH0_VARIANT 0 -#define DMA1_CH1_VARIANT 0 -#define DMA1_CH2_VARIANT 0 -#define DMA1_CH3_VARIANT 0 -#define DMA1_CH4_VARIANT 0 -#define DMA1_CH5_VARIANT 0 -#define DMA1_CH6_VARIANT 0 -#define DMA1_CH7_VARIANT 0 -#define DMA2_CH0_VARIANT 0 -#define DMA2_CH1_VARIANT 0 -#define DMA2_CH2_VARIANT 0 -#define DMA2_CH3_VARIANT 0 -#define DMA2_CH4_VARIANT 0 -#define DMA2_CH5_VARIANT 0 -#define DMA2_CH6_VARIANT 0 -#define DMA2_CH7_VARIANT 0 - -#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief DMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc. - */ -const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { - {DMA1_Stream0, &DMA1->LIFCR, DMA1_CH0_VARIANT, 0, 0, STM32_DMA1_CH0_NUMBER}, - {DMA1_Stream1, &DMA1->LIFCR, DMA1_CH1_VARIANT, 6, 1, STM32_DMA1_CH1_NUMBER}, - {DMA1_Stream2, &DMA1->LIFCR, DMA1_CH2_VARIANT, 16, 2, STM32_DMA1_CH2_NUMBER}, - {DMA1_Stream3, &DMA1->LIFCR, DMA1_CH3_VARIANT, 22, 3, STM32_DMA1_CH3_NUMBER}, - {DMA1_Stream4, &DMA1->HIFCR, DMA1_CH4_VARIANT, 0, 4, STM32_DMA1_CH4_NUMBER}, - {DMA1_Stream5, &DMA1->HIFCR, DMA1_CH5_VARIANT, 6, 5, STM32_DMA1_CH5_NUMBER}, - {DMA1_Stream6, &DMA1->HIFCR, DMA1_CH6_VARIANT, 16, 6, STM32_DMA1_CH6_NUMBER}, - {DMA1_Stream7, &DMA1->HIFCR, DMA1_CH7_VARIANT, 22, 7, STM32_DMA1_CH7_NUMBER}, - {DMA2_Stream0, &DMA2->LIFCR, DMA2_CH0_VARIANT, 0, 8, STM32_DMA2_CH0_NUMBER}, - {DMA2_Stream1, &DMA2->LIFCR, DMA2_CH1_VARIANT, 6, 9, STM32_DMA2_CH1_NUMBER}, - {DMA2_Stream2, &DMA2->LIFCR, DMA2_CH2_VARIANT, 16, 10, STM32_DMA2_CH2_NUMBER}, - {DMA2_Stream3, &DMA2->LIFCR, DMA2_CH3_VARIANT, 22, 11, STM32_DMA2_CH3_NUMBER}, - {DMA2_Stream4, &DMA2->HIFCR, DMA2_CH4_VARIANT, 0, 12, STM32_DMA2_CH4_NUMBER}, - {DMA2_Stream5, &DMA2->HIFCR, DMA2_CH5_VARIANT, 6, 13, STM32_DMA2_CH5_NUMBER}, - {DMA2_Stream6, &DMA2->HIFCR, DMA2_CH6_VARIANT, 16, 14, STM32_DMA2_CH6_NUMBER}, - {DMA2_Stream7, &DMA2->HIFCR, DMA2_CH7_VARIANT, 22, 15, STM32_DMA2_CH7_NUMBER}, -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Global DMA-related data structures. - */ -static struct { - /** - * @brief Mask of the allocated streams. - */ - uint32_t allocated_mask; - /** - * @brief DMA IRQ redirectors. - */ - struct { - /** - * @brief DMA callback function. - */ - stm32_dmaisr_t func; - /** - * @brief DMA callback parameter. - */ - void *param; - } streams[STM32_DMA_STREAMS]; -} dma; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief DMA1 stream 0 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH0_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 0U) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = flags << 0U; - if (dma.streams[0].func) - dma.streams[0].func(dma.streams[0].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 6U) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = flags << 6U; - if (dma.streams[1].func) - dma.streams[1].func(dma.streams[1].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 2 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 16U) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = flags << 16U; - if (dma.streams[2].func) - dma.streams[2].func(dma.streams[2].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 22U) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = flags << 22U; - if (dma.streams[3].func) - dma.streams[3].func(dma.streams[3].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 4 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 0U) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = flags << 0U; - if (dma.streams[4].func) - dma.streams[4].func(dma.streams[4].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 6U) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = flags << 6U; - if (dma.streams[5].func) - dma.streams[5].func(dma.streams[5].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 6 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 16U) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = flags << 16U; - if (dma.streams[6].func) - dma.streams[6].func(dma.streams[6].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 7 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 22U) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = flags << 22U; - if (dma.streams[7].func) - dma.streams[7].func(dma.streams[7].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 0 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH0_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 0U) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = flags << 0U; - if (dma.streams[8].func) - dma.streams[8].func(dma.streams[8].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 6U) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = flags << 6U; - if (dma.streams[9].func) - dma.streams[9].func(dma.streams[9].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 2 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 16U) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = flags << 16U; - if (dma.streams[10].func) - dma.streams[10].func(dma.streams[10].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 22U) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = flags << 22U; - if (dma.streams[11].func) - dma.streams[11].func(dma.streams[11].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 4 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 0U) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = flags << 0U; - if (dma.streams[12].func) - dma.streams[12].func(dma.streams[12].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 6U) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = flags << 6U; - if (dma.streams[13].func) - dma.streams[13].func(dma.streams[13].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 6 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 16U) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = flags << 16U; - if (dma.streams[14].func) - dma.streams[14].func(dma.streams[14].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 7 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 22U) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = flags << 22U; - if (dma.streams[15].func) - dma.streams[15].func(dma.streams[15].param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA helper initialization. - * - * @init - */ -void dmaInit(void) { - unsigned i; - - dma.allocated_mask = 0U; - for (i = 0U; i < STM32_DMA_STREAMS; i++) { - _stm32_dma_streams[i].stream->CR = STM32_DMA_CR_RESET_VALUE; - dma.streams[i].func = NULL; - } - DMA1->LIFCR = 0xFFFFFFFFU; - DMA1->HIFCR = 0xFFFFFFFFU; - DMA2->LIFCR = 0xFFFFFFFFU; - DMA2->HIFCR = 0xFFFFFFFFU; -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific stream or: - * - @p STM32_DMA_STREAM_ID_ANY for any stream. - * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream - * on DMA1. - * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream - * on DMA2. - * . - * @param[in] priority IRQ priority for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_dma_stream_t - * structure. - * @retval NULL if a/the stream is not available. - * - * @iclass - */ -const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - uint32_t i, startid, endid; - - osalDbgCheckClassI(); - - if (id < STM32_DMA_STREAMS) { - startid = id; - endid = id; - } -#if STM32_DMA_SUPPORTS_DMAMUX == TRUE - else if (id == STM32_DMA_STREAM_ID_ANY) { - startid = 0U; - endid = STM32_DMA_STREAMS - 1U; - } - else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) { - startid = 0U; - endid = (STM32_DMA_STREAMS / 2U) - 1U; - } - else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) { - startid = (STM32_DMA_STREAMS / 2U) - 1U; - endid = STM32_DMA_STREAMS - 1U; - } -#endif - else { - osalDbgCheck(false); - return NULL; - } - - for (i = startid; i <= endid; i++) { - uint32_t mask = (1U << i); - if ((dma.allocated_mask & mask) == 0U) { - const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i); - - /* Installs the DMA handler.*/ - dma.streams[i].func = func; - dma.streams[i].param = param; - dma.allocated_mask |= mask; - - /* Enabling DMA clocks required by the current streams set.*/ - if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) { - rccEnableDMA1(true); - } - if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) { - rccEnableDMA2(true); - } - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX) - /* Enabling DMAMUX if present.*/ - if (dma.allocated_mask != 0U) { - rccEnableDMAMUX(true); - } -#endif - - /* Putting the stream in a safe state.*/ - dmaStreamDisable(dmastp); - dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE; - dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE; - - /* Enables the associated IRQ vector if a callback is defined.*/ - if (func != NULL) { - nvicEnableVector(dmastp->vector, priority); - } - - return dmastp; - } - } - - return NULL; -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific stream or: - * - @p STM32_DMA_STREAM_ID_ANY for any stream. - * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream - * on DMA1. - * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream - * on DMA2. - * . - * @param[in] priority IRQ priority for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_dma_stream_t - * structure. - * @retval NULL if a/the stream is not available. - * - * @api - */ -const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - const stm32_dma_stream_t *dmastp; - - osalSysLock(); - dmastp = dmaStreamAllocI(id, priority, func, param); - osalSysUnlock(); - - return dmastp; -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @iclass - */ -void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) { - - osalDbgCheck(dmastp != NULL); - - /* Check if the streams is not taken.*/ - osalDbgAssert((dma.allocated_mask & (1U << dmastp->selfindex)) != 0U, - "not allocated"); - - /* Disables the associated IRQ vector.*/ - nvicDisableVector(dmastp->vector); - - /* Marks the stream as not allocated.*/ - dma.allocated_mask &= ~(1U << dmastp->selfindex); - - /* Shutting down clocks that are no more required, if any.*/ - if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) { - rccDisableDMA1(); - } - if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) { - rccDisableDMA2(); - } - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX) - /* Shutting down DMAMUX if present.*/ - if (dma.allocated_mask == 0U) { - rccDisableDMAMUX(); - } -#endif -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @api - */ -void dmaStreamFree(const stm32_dma_stream_t *dmastp) { - - osalSysLock(); - dmaStreamFreeI(dmastp); - osalSysUnlock(); -} - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) -/** - * @brief Associates a peripheral request to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure - * @param[in] per peripheral identifier - * - * @special - */ -void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) { - - osalDbgCheck(per < 256U); - - dmastp->mux->CCR = per; -} -#endif - -#endif /* STM32_DMA_REQUIRED */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file DMAv2/stm32_dma.c + * @brief Enhanced DMA helper driver code. + * + * @addtogroup STM32_DMA + * @details DMA sharing helper driver. In the STM32 the DMA streams are a + * shared resource, this driver allows to allocate and free DMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The DMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating streams. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring DMA services + has been enabled.*/ +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the DMA1 streams in @p dma.allocated_mask. + */ +#define STM32_DMA1_STREAMS_MASK 0x000000FFU + +/** + * @brief Mask of the DMA2 streams in @p dma.allocated_mask. + */ +#define STM32_DMA2_STREAMS_MASK 0x0000FF00U + +#if STM32_DMA_SUPPORTS_DMAMUX == TRUE + +#define DMA1_CH0_VARIANT DMAMUX1_Channel0 +#define DMA1_CH1_VARIANT DMAMUX1_Channel1 +#define DMA1_CH2_VARIANT DMAMUX1_Channel2 +#define DMA1_CH3_VARIANT DMAMUX1_Channel3 +#define DMA1_CH4_VARIANT DMAMUX1_Channel4 +#define DMA1_CH5_VARIANT DMAMUX1_Channel5 +#define DMA1_CH6_VARIANT DMAMUX1_Channel6 +#define DMA1_CH7_VARIANT DMAMUX1_Channel7 +#define DMA2_CH0_VARIANT DMAMUX1_Channel8 +#define DMA2_CH1_VARIANT DMAMUX1_Channel9 +#define DMA2_CH2_VARIANT DMAMUX1_Channel10 +#define DMA2_CH3_VARIANT DMAMUX1_Channel11 +#define DMA2_CH4_VARIANT DMAMUX1_Channel12 +#define DMA2_CH5_VARIANT DMAMUX1_Channel13 +#define DMA2_CH6_VARIANT DMAMUX1_Channel14 +#define DMA2_CH7_VARIANT DMAMUX1_Channel15 + +#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ + +#define DMA1_CH0_VARIANT 0 +#define DMA1_CH1_VARIANT 0 +#define DMA1_CH2_VARIANT 0 +#define DMA1_CH3_VARIANT 0 +#define DMA1_CH4_VARIANT 0 +#define DMA1_CH5_VARIANT 0 +#define DMA1_CH6_VARIANT 0 +#define DMA1_CH7_VARIANT 0 +#define DMA2_CH0_VARIANT 0 +#define DMA2_CH1_VARIANT 0 +#define DMA2_CH2_VARIANT 0 +#define DMA2_CH3_VARIANT 0 +#define DMA2_CH4_VARIANT 0 +#define DMA2_CH5_VARIANT 0 +#define DMA2_CH6_VARIANT 0 +#define DMA2_CH7_VARIANT 0 + +#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief DMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc. + */ +const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { + {DMA1_Stream0, &DMA1->LIFCR, DMA1_CH0_VARIANT, 0, 0, STM32_DMA1_CH0_NUMBER}, + {DMA1_Stream1, &DMA1->LIFCR, DMA1_CH1_VARIANT, 6, 1, STM32_DMA1_CH1_NUMBER}, + {DMA1_Stream2, &DMA1->LIFCR, DMA1_CH2_VARIANT, 16, 2, STM32_DMA1_CH2_NUMBER}, + {DMA1_Stream3, &DMA1->LIFCR, DMA1_CH3_VARIANT, 22, 3, STM32_DMA1_CH3_NUMBER}, + {DMA1_Stream4, &DMA1->HIFCR, DMA1_CH4_VARIANT, 0, 4, STM32_DMA1_CH4_NUMBER}, + {DMA1_Stream5, &DMA1->HIFCR, DMA1_CH5_VARIANT, 6, 5, STM32_DMA1_CH5_NUMBER}, + {DMA1_Stream6, &DMA1->HIFCR, DMA1_CH6_VARIANT, 16, 6, STM32_DMA1_CH6_NUMBER}, + {DMA1_Stream7, &DMA1->HIFCR, DMA1_CH7_VARIANT, 22, 7, STM32_DMA1_CH7_NUMBER}, + {DMA2_Stream0, &DMA2->LIFCR, DMA2_CH0_VARIANT, 0, 8, STM32_DMA2_CH0_NUMBER}, + {DMA2_Stream1, &DMA2->LIFCR, DMA2_CH1_VARIANT, 6, 9, STM32_DMA2_CH1_NUMBER}, + {DMA2_Stream2, &DMA2->LIFCR, DMA2_CH2_VARIANT, 16, 10, STM32_DMA2_CH2_NUMBER}, + {DMA2_Stream3, &DMA2->LIFCR, DMA2_CH3_VARIANT, 22, 11, STM32_DMA2_CH3_NUMBER}, + {DMA2_Stream4, &DMA2->HIFCR, DMA2_CH4_VARIANT, 0, 12, STM32_DMA2_CH4_NUMBER}, + {DMA2_Stream5, &DMA2->HIFCR, DMA2_CH5_VARIANT, 6, 13, STM32_DMA2_CH5_NUMBER}, + {DMA2_Stream6, &DMA2->HIFCR, DMA2_CH6_VARIANT, 16, 14, STM32_DMA2_CH6_NUMBER}, + {DMA2_Stream7, &DMA2->HIFCR, DMA2_CH7_VARIANT, 22, 15, STM32_DMA2_CH7_NUMBER}, +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Global DMA-related data structures. + */ +static struct { + /** + * @brief Mask of the allocated streams. + */ + uint32_t allocated_mask; + /** + * @brief DMA IRQ redirectors. + */ + struct { + /** + * @brief DMA callback function. + */ + stm32_dmaisr_t func; + /** + * @brief DMA callback parameter. + */ + void *param; + } streams[STM32_DMA_STREAMS]; +} dma; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief DMA1 stream 0 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH0_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 0U) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = flags << 0U; + if (dma.streams[0].func) + dma.streams[0].func(dma.streams[0].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 6U) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = flags << 6U; + if (dma.streams[1].func) + dma.streams[1].func(dma.streams[1].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 16U) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = flags << 16U; + if (dma.streams[2].func) + dma.streams[2].func(dma.streams[2].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 22U) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = flags << 22U; + if (dma.streams[3].func) + dma.streams[3].func(dma.streams[3].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 0U) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = flags << 0U; + if (dma.streams[4].func) + dma.streams[4].func(dma.streams[4].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 6U) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = flags << 6U; + if (dma.streams[5].func) + dma.streams[5].func(dma.streams[5].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 6 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 16U) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = flags << 16U; + if (dma.streams[6].func) + dma.streams[6].func(dma.streams[6].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 7 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 22U) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = flags << 22U; + if (dma.streams[7].func) + dma.streams[7].func(dma.streams[7].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 0 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH0_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 0U) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = flags << 0U; + if (dma.streams[8].func) + dma.streams[8].func(dma.streams[8].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 6U) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = flags << 6U; + if (dma.streams[9].func) + dma.streams[9].func(dma.streams[9].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 16U) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = flags << 16U; + if (dma.streams[10].func) + dma.streams[10].func(dma.streams[10].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 22U) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = flags << 22U; + if (dma.streams[11].func) + dma.streams[11].func(dma.streams[11].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 0U) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = flags << 0U; + if (dma.streams[12].func) + dma.streams[12].func(dma.streams[12].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 6U) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = flags << 6U; + if (dma.streams[13].func) + dma.streams[13].func(dma.streams[13].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 6 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 16U) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = flags << 16U; + if (dma.streams[14].func) + dma.streams[14].func(dma.streams[14].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 7 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 22U) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = flags << 22U; + if (dma.streams[15].func) + dma.streams[15].func(dma.streams[15].param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA helper initialization. + * + * @init + */ +void dmaInit(void) { + unsigned i; + + dma.allocated_mask = 0U; + for (i = 0U; i < STM32_DMA_STREAMS; i++) { + _stm32_dma_streams[i].stream->CR = STM32_DMA_CR_RESET_VALUE; + dma.streams[i].func = NULL; + } + DMA1->LIFCR = 0xFFFFFFFFU; + DMA1->HIFCR = 0xFFFFFFFFU; + DMA2->LIFCR = 0xFFFFFFFFU; + DMA2->HIFCR = 0xFFFFFFFFU; +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific stream or: + * - @p STM32_DMA_STREAM_ID_ANY for any stream. + * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream + * on DMA1. + * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream + * on DMA2. + * . + * @param[in] priority IRQ priority for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_dma_stream_t + * structure. + * @retval NULL if a/the stream is not available. + * + * @iclass + */ +const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + uint32_t i, startid, endid; + + osalDbgCheckClassI(); + + if (id < STM32_DMA_STREAMS) { + startid = id; + endid = id; + } +#if STM32_DMA_SUPPORTS_DMAMUX == TRUE + else if (id == STM32_DMA_STREAM_ID_ANY) { + startid = 0U; + endid = STM32_DMA_STREAMS - 1U; + } + else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) { + startid = 0U; + endid = (STM32_DMA_STREAMS / 2U) - 1U; + } + else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) { + startid = (STM32_DMA_STREAMS / 2U) - 1U; + endid = STM32_DMA_STREAMS - 1U; + } +#endif + else { + osalDbgCheck(false); + return NULL; + } + + for (i = startid; i <= endid; i++) { + uint32_t mask = (1U << i); + if ((dma.allocated_mask & mask) == 0U) { + const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i); + + /* Installs the DMA handler.*/ + dma.streams[i].func = func; + dma.streams[i].param = param; + dma.allocated_mask |= mask; + + /* Enabling DMA clocks required by the current streams set.*/ + if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) { + rccEnableDMA1(true); + } + if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) { + rccEnableDMA2(true); + } + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX) + /* Enabling DMAMUX if present.*/ + if (dma.allocated_mask != 0U) { + rccEnableDMAMUX(true); + } +#endif + + /* Putting the stream in a safe state.*/ + dmaStreamDisable(dmastp); + dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE; + dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE; + + /* Enables the associated IRQ vector if a callback is defined.*/ + if (func != NULL) { + nvicEnableVector(dmastp->vector, priority); + } + + return dmastp; + } + } + + return NULL; +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific stream or: + * - @p STM32_DMA_STREAM_ID_ANY for any stream. + * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream + * on DMA1. + * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream + * on DMA2. + * . + * @param[in] priority IRQ priority for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_dma_stream_t + * structure. + * @retval NULL if a/the stream is not available. + * + * @api + */ +const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + const stm32_dma_stream_t *dmastp; + + osalSysLock(); + dmastp = dmaStreamAllocI(id, priority, func, param); + osalSysUnlock(); + + return dmastp; +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @iclass + */ +void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) { + + osalDbgCheck(dmastp != NULL); + + /* Check if the streams is not taken.*/ + osalDbgAssert((dma.allocated_mask & (1U << dmastp->selfindex)) != 0U, + "not allocated"); + + /* Disables the associated IRQ vector.*/ + nvicDisableVector(dmastp->vector); + + /* Marks the stream as not allocated.*/ + dma.allocated_mask &= ~(1U << dmastp->selfindex); + + /* Shutting down clocks that are no more required, if any.*/ + if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) { + rccDisableDMA1(); + } + if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) { + rccDisableDMA2(); + } + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX) + /* Shutting down DMAMUX if present.*/ + if (dma.allocated_mask == 0U) { + rccDisableDMAMUX(); + } +#endif +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @api + */ +void dmaStreamFree(const stm32_dma_stream_t *dmastp) { + + osalSysLock(); + dmaStreamFreeI(dmastp); + osalSysUnlock(); +} + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) +/** + * @brief Associates a peripheral request to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure + * @param[in] per peripheral identifier + * + * @special + */ +void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) { + + osalDbgCheck(per < 256U); + + dmastp->mux->CCR = per; +} +#endif + +#endif /* STM32_DMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h b/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h index 2562039328..dbd22c1e55 100644 --- a/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h +++ b/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h @@ -1,682 +1,682 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file DMAv2/stm32_dma.h - * @brief Enhanced-DMA helper driver header. - * - * @addtogroup STM32_DMA - * @{ - */ - -#ifndef STM32_DMA_H -#define STM32_DMA_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief DMA capability. - * @details if @p TRUE then the DMA is able of burst transfers, FIFOs, - * scatter gather and other advanced features. - */ -#define STM32_DMA_ADVANCED TRUE - -/** - * @brief Total number of DMA streams. - * @details This is the total number of streams among all the DMA units. - */ -#define STM32_DMA_STREAMS 16U - -/** - * @brief Mask of the ISR bits passed to the DMA callback functions. - */ -#define STM32_DMA_ISR_MASK 0x3DU - -/** - * @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) & 7U) * 4U)) & 15U) - -/** - * @brief Checks if a DMA priority is within the valid range. - * @param[in] prio DMA priority - * - * @retval The check result. - * @retval false invalid DMA priority. - * @retval true correct DMA priority. - */ -#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) - -#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__) -/** - * @brief Checks if a DMA stream id is within the valid range. - * - * @param[in] id DMA stream id - * @retval The check result. - * @retval false invalid DMA stream. - * @retval true correct DMA stream. - */ -#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) <= STM32_DMA_STREAMS)) -#else /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ -#if STM32_HAS_DMA2 == TRUE -#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) <= (STM32_DMA_STREAMS + 2))) -#else -#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ - ((id) <= (STM32_DMA_STREAMS + 1))) -#endif -#endif /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ - -/** - * @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) - 1U) * 8U) + (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) \ - (1U << 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) (((1U << (id)) & (mask))) - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__) -/** - * @name Special stream identifiers - * @{ - */ -#define STM32_DMA_STREAM_ID_ANY STM32_DMA_STREAMS -#define STM32_DMA_STREAM_ID_ANY_DMA1 (STM32_DMA_STREAM_ID_ANY + 1) -#if STM32_HAS_DMA2 == TRUE -#define STM32_DMA_STREAM_ID_ANY_DMA2 (STM32_DMA_STREAM_ID_ANY_DMA1 + 1) -#endif -/** @} */ -#endif - -/** - * @name DMA streams identifiers - * @{ - */ -/** - * @brief Returns a pointer to a stm32_dma_stream_t structure. - * - * @param[in] id the stream numeric identifier - * @return A pointer to the stm32_dma_stream_t constant structure - * associated to the DMA stream. - */ -#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) - -#define STM32_DMA1_STREAM0 STM32_DMA_STREAM(0) -#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1) -#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2) -#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3) -#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4) -#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5) -#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6) -#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7) -#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8) -#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9) -#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10) -#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11) -#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12) -#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13) -#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14) -#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15) -/** @} */ - -/** - * @name CR register constants common to all DMA types - * @{ - */ -#define STM32_DMA_CR_RESET_VALUE 0x00000000U -#define STM32_DMA_CR_EN DMA_SxCR_EN -#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE -#define STM32_DMA_CR_HTIE DMA_SxCR_HTIE -#define STM32_DMA_CR_TCIE DMA_SxCR_TCIE -#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL -#define STM32_DMA_CR_DIR_MASK DMA_SxCR_DIR -#define STM32_DMA_CR_DIR_P2M 0 -#define STM32_DMA_CR_DIR_M2P DMA_SxCR_DIR_0 -#define STM32_DMA_CR_DIR_M2M DMA_SxCR_DIR_1 -#define STM32_DMA_CR_CIRC DMA_SxCR_CIRC -#define STM32_DMA_CR_PINC DMA_SxCR_PINC -#define STM32_DMA_CR_MINC DMA_SxCR_MINC -#define STM32_DMA_CR_PSIZE_MASK DMA_SxCR_PSIZE -#define STM32_DMA_CR_PSIZE_BYTE 0 -#define STM32_DMA_CR_PSIZE_HWORD DMA_SxCR_PSIZE_0 -#define STM32_DMA_CR_PSIZE_WORD DMA_SxCR_PSIZE_1 -#define STM32_DMA_CR_MSIZE_MASK DMA_SxCR_MSIZE -#define STM32_DMA_CR_MSIZE_BYTE 0 -#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0 -#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1 -#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ - STM32_DMA_CR_MSIZE_MASK) -#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL -#define STM32_DMA_CR_PL(n) ((n) << 16U) -/** @} */ - -/** - * @name CR register constants only found in DMAv2 - * @{ - */ -#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE -#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL -#define STM32_DMA_CR_PINCOS DMA_SxCR_PINCOS -#define STM32_DMA_CR_DBM DMA_SxCR_DBM -#define STM32_DMA_CR_CT DMA_SxCR_CT -#define STM32_DMA_CR_PBURST_MASK DMA_SxCR_PBURST -#define STM32_DMA_CR_PBURST_SINGLE 0U -#define STM32_DMA_CR_PBURST_INCR4 DMA_SxCR_PBURST_0 -#define STM32_DMA_CR_PBURST_INCR8 DMA_SxCR_PBURST_1 -#define STM32_DMA_CR_PBURST_INCR16 (DMA_SxCR_PBURST_0 | DMA_SxCR_PBURST_1) -#define STM32_DMA_CR_MBURST_MASK DMA_SxCR_MBURST -#define STM32_DMA_CR_MBURST_SINGLE 0U -#define STM32_DMA_CR_MBURST_INCR4 DMA_SxCR_MBURST_0 -#define STM32_DMA_CR_MBURST_INCR8 DMA_SxCR_MBURST_1 -#define STM32_DMA_CR_MBURST_INCR16 (DMA_SxCR_MBURST_0 | DMA_SxCR_MBURST_1) -#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(__DOXYGEN__) -#define STM32_DMA_CR_CHSEL_MASK DMA_SxCR_CHSEL -#define STM32_DMA_CR_CHSEL(n) ((n) << 25U) -#else -#define STM32_DMA_CR_CHSEL_MASK 0U -#define STM32_DMA_CR_CHSEL(n) 0U -#endif -/** @} */ - -/** - * @name FCR register constants only found in DMAv2 - * @{ - */ -#define STM32_DMA_FCR_RESET_VALUE 0x00000021U -#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE -#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS -#define STM32_DMA_FCR_DMDIS DMA_SxFCR_DMDIS -#define STM32_DMA_FCR_FTH_MASK DMA_SxFCR_FTH -#define STM32_DMA_FCR_FTH_1Q 0 -#define STM32_DMA_FCR_FTH_HALF DMA_SxFCR_FTH_0 -#define STM32_DMA_FCR_FTH_3Q DMA_SxFCR_FTH_1 -#define STM32_DMA_FCR_FTH_FULL (DMA_SxFCR_FTH_0 | DMA_SxFCR_FTH_1) -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - */ -#define STM32_DMA_ISR_FEIF DMA_LISR_FEIF0 -#define STM32_DMA_ISR_DMEIF DMA_LISR_DMEIF0 -#define STM32_DMA_ISR_TEIF DMA_LISR_TEIF0 -#define STM32_DMA_ISR_HTIF DMA_LISR_HTIF0 -#define STM32_DMA_ISR_TCIF DMA_LISR_TCIF0 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_DMA_SUPPORTS_DMAMUX) -#error "STM32_DMA_SUPPORTS_DMAMUX not defined in registry" -#endif - -#if !defined(STM32_HAS_DMA1) -#error "STM32_HAS_DMA1 missing in registry" -#endif - -#if !defined(STM32_HAS_DMA2) -#error "STM32_HAS_DMA2 missing in registry" -#endif - -#if !defined(STM32_DMA1_CH0_HANDLER) -#error "STM32_DMA1_CH0_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH1_HANDLER) -#error "STM32_DMA1_CH1_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH2_HANDLER) -#error "STM32_DMA1_CH2_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH3_HANDLER) -#error "STM32_DMA1_CH3_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH4_HANDLER) -#error "STM32_DMA1_CH4_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH5_HANDLER) -#error "STM32_DMA1_CH5_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH6_HANDLER) -#error "STM32_DMA1_CH6_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH7_HANDLER) -#error "STM32_DMA1_CH7_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH0_HANDLER) -#error "STM32_DMA2_CH0_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH1_HANDLER) -#error "STM32_DMA2_CH1_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH2_HANDLER) -#error "STM32_DMA2_CH2_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH3_HANDLER) -#error "STM32_DMA2_CH3_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH4_HANDLER) -#error "STM32_DMA2_CH4_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH5_HANDLER) -#error "STM32_DMA2_CH5_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH6_HANDLER) -#error "STM32_DMA2_CH6_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH7_HANDLER) -#error "STM32_DMA2_CH7_HANDLER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH0_NUMBER) -#error "STM32_DMA1_CH0_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH1_NUMBER) -#error "STM32_DMA1_CH1_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH2_NUMBER) -#error "STM32_DMA1_CH2_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH3_NUMBER) -#error "STM32_DMA1_CH3_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH4_NUMBER) -#error "STM32_DMA1_CH4_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH5_NUMBER) -#error "STM32_DMA1_CH5_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH6_NUMBER) -#error "STM32_DMA1_CH6_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA1_CH7_NUMBER) -#error "STM32_DMA1_CH7_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH0_NUMBER) -#error "STM32_DMA2_CH0_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH1_NUMBER) -#error "STM32_DMA2_CH1_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH2_NUMBER) -#error "STM32_DMA2_CH2_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH3_NUMBER) -#error "STM32_DMA2_CH3_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH4_NUMBER) -#error "STM32_DMA2_CH4_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH5_NUMBER) -#error "STM32_DMA2_CH5_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH6_NUMBER) -#error "STM32_DMA2_CH6_NUMBER missing in registry" -#endif - -#if !defined(STM32_DMA2_CH7_NUMBER) -#error "STM32_DMA2_CH7_NUMBER missing in registry" -#endif - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) -#include "stm32_dmamux.h" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the xISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); - -/** - * @brief STM32 DMA stream descriptor structure. - */ -typedef struct { - DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */ - volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) - DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */ -#else - uint8_t dummy; /**< @brief Filler. */ -#endif - uint8_t shift; /**< @brief Bits offset in xIFCR - register. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_dma_stream_t; - -/*===========================================================================*/ -/* 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 dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the PAR register - * - * @special - */ -#define dmaStreamSetPeripheral(dmastp, addr) { \ - (dmastp)->stream->PAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the M0AR register - * - * @special - */ -#define dmaStreamSetMemory0(dmastp, addr) { \ - (dmastp)->stream->M0AR = (uint32_t)(addr); \ -} - -/** - * @brief Associates an alternate memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the M1AR register - * - * @special - */ -#define dmaStreamSetMemory1(dmastp, addr) { \ - (dmastp)->stream->M1AR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define dmaStreamSetTransactionSize(dmastp, size) { \ - (dmastp)->stream->NDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->stream->NDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CR register - * - * @special - */ -#define dmaStreamSetMode(dmastp, mode) { \ - (dmastp)->stream->CR = (uint32_t)(mode); \ -} - -/** - * @brief Programs the stream FIFO settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the FCR register - * - * @special - */ -#define dmaStreamSetFIFO(dmastp, mode) { \ - (dmastp)->stream->FCR = (uint32_t)(mode); \ -} - -/** - * @brief DMA stream enable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamEnable(dmastp) { \ - (dmastp)->stream->CR |= STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream disable. - * @details The function disables the specified stream, waits for the disable - * operation to complete and then clears any pending interrupt. - * @note This function can be invoked in both ISR or thread context. - * @note Interrupts enabling flags are set to zero after this call, see - * bug 3607518. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamDisable(dmastp) { \ - (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE | \ - STM32_DMA_CR_EN); \ - while (((dmastp)->stream->CR & STM32_DMA_CR_EN) != 0) \ - ; \ - dmaStreamClearInterrupt(dmastp); \ -} - -/** - * @brief DMA stream interrupt sources clear. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamClearInterrupt(dmastp) { \ - *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->shift; \ -} - -/** - * @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 dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @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); \ - dmaStreamEnable(dmastp); \ -} - -/** - * @brief Polled wait for DMA transfer end. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - */ -#define dmaWaitCompletion(dmastp) { \ - (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE); \ - while ((dmastp)->stream->CR & STM32_DMA_CR_EN) \ - ; \ - dmaStreamClearInterrupt(dmastp); \ -} - -/** - * @brief DMA stream current target. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAlloc(). - * @post After use the stream can be released using @p dmaStreamFree(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return Current memory target index. - * - * @special - */ -#define dmaStreamGetCurrentTarget(dmastp) \ - (((dmastp)->stream->CR >> DMA_SxCR_CT_Pos) & 1U) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dmaInit(void); - const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - void dmaStreamFreeI(const stm32_dma_stream_t *dmastp); - void dmaStreamFree(const stm32_dma_stream_t *dmastp); -#if STM32_DMA_SUPPORTS_DMAMUX == TRUE - void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMA_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file DMAv2/stm32_dma.h + * @brief Enhanced-DMA helper driver header. + * + * @addtogroup STM32_DMA + * @{ + */ + +#ifndef STM32_DMA_H +#define STM32_DMA_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief DMA capability. + * @details if @p TRUE then the DMA is able of burst transfers, FIFOs, + * scatter gather and other advanced features. + */ +#define STM32_DMA_ADVANCED TRUE + +/** + * @brief Total number of DMA streams. + * @details This is the total number of streams among all the DMA units. + */ +#define STM32_DMA_STREAMS 16U + +/** + * @brief Mask of the ISR bits passed to the DMA callback functions. + */ +#define STM32_DMA_ISR_MASK 0x3DU + +/** + * @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) & 7U) * 4U)) & 15U) + +/** + * @brief Checks if a DMA priority is within the valid range. + * @param[in] prio DMA priority + * + * @retval The check result. + * @retval false invalid DMA priority. + * @retval true correct DMA priority. + */ +#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) + +#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__) +/** + * @brief Checks if a DMA stream id is within the valid range. + * + * @param[in] id DMA stream id + * @retval The check result. + * @retval false invalid DMA stream. + * @retval true correct DMA stream. + */ +#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) <= STM32_DMA_STREAMS)) +#else /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ +#if STM32_HAS_DMA2 == TRUE +#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) <= (STM32_DMA_STREAMS + 2))) +#else +#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \ + ((id) <= (STM32_DMA_STREAMS + 1))) +#endif +#endif /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */ + +/** + * @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) - 1U) * 8U) + (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) \ + (1U << 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) (((1U << (id)) & (mask))) + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__) +/** + * @name Special stream identifiers + * @{ + */ +#define STM32_DMA_STREAM_ID_ANY STM32_DMA_STREAMS +#define STM32_DMA_STREAM_ID_ANY_DMA1 (STM32_DMA_STREAM_ID_ANY + 1) +#if STM32_HAS_DMA2 == TRUE +#define STM32_DMA_STREAM_ID_ANY_DMA2 (STM32_DMA_STREAM_ID_ANY_DMA1 + 1) +#endif +/** @} */ +#endif + +/** + * @name DMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_dma_stream_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_dma_stream_t constant structure + * associated to the DMA stream. + */ +#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) + +#define STM32_DMA1_STREAM0 STM32_DMA_STREAM(0) +#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1) +#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2) +#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3) +#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4) +#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5) +#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6) +#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7) +#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8) +#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9) +#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10) +#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11) +#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12) +#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13) +#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14) +#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15) +/** @} */ + +/** + * @name CR register constants common to all DMA types + * @{ + */ +#define STM32_DMA_CR_RESET_VALUE 0x00000000U +#define STM32_DMA_CR_EN DMA_SxCR_EN +#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE +#define STM32_DMA_CR_HTIE DMA_SxCR_HTIE +#define STM32_DMA_CR_TCIE DMA_SxCR_TCIE +#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL +#define STM32_DMA_CR_DIR_MASK DMA_SxCR_DIR +#define STM32_DMA_CR_DIR_P2M 0 +#define STM32_DMA_CR_DIR_M2P DMA_SxCR_DIR_0 +#define STM32_DMA_CR_DIR_M2M DMA_SxCR_DIR_1 +#define STM32_DMA_CR_CIRC DMA_SxCR_CIRC +#define STM32_DMA_CR_PINC DMA_SxCR_PINC +#define STM32_DMA_CR_MINC DMA_SxCR_MINC +#define STM32_DMA_CR_PSIZE_MASK DMA_SxCR_PSIZE +#define STM32_DMA_CR_PSIZE_BYTE 0 +#define STM32_DMA_CR_PSIZE_HWORD DMA_SxCR_PSIZE_0 +#define STM32_DMA_CR_PSIZE_WORD DMA_SxCR_PSIZE_1 +#define STM32_DMA_CR_MSIZE_MASK DMA_SxCR_MSIZE +#define STM32_DMA_CR_MSIZE_BYTE 0 +#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0 +#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1 +#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ + STM32_DMA_CR_MSIZE_MASK) +#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL +#define STM32_DMA_CR_PL(n) ((n) << 16U) +/** @} */ + +/** + * @name CR register constants only found in DMAv2 + * @{ + */ +#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE +#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL +#define STM32_DMA_CR_PINCOS DMA_SxCR_PINCOS +#define STM32_DMA_CR_DBM DMA_SxCR_DBM +#define STM32_DMA_CR_CT DMA_SxCR_CT +#define STM32_DMA_CR_PBURST_MASK DMA_SxCR_PBURST +#define STM32_DMA_CR_PBURST_SINGLE 0U +#define STM32_DMA_CR_PBURST_INCR4 DMA_SxCR_PBURST_0 +#define STM32_DMA_CR_PBURST_INCR8 DMA_SxCR_PBURST_1 +#define STM32_DMA_CR_PBURST_INCR16 (DMA_SxCR_PBURST_0 | DMA_SxCR_PBURST_1) +#define STM32_DMA_CR_MBURST_MASK DMA_SxCR_MBURST +#define STM32_DMA_CR_MBURST_SINGLE 0U +#define STM32_DMA_CR_MBURST_INCR4 DMA_SxCR_MBURST_0 +#define STM32_DMA_CR_MBURST_INCR8 DMA_SxCR_MBURST_1 +#define STM32_DMA_CR_MBURST_INCR16 (DMA_SxCR_MBURST_0 | DMA_SxCR_MBURST_1) +#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(__DOXYGEN__) +#define STM32_DMA_CR_CHSEL_MASK DMA_SxCR_CHSEL +#define STM32_DMA_CR_CHSEL(n) ((n) << 25U) +#else +#define STM32_DMA_CR_CHSEL_MASK 0U +#define STM32_DMA_CR_CHSEL(n) 0U +#endif +/** @} */ + +/** + * @name FCR register constants only found in DMAv2 + * @{ + */ +#define STM32_DMA_FCR_RESET_VALUE 0x00000021U +#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE +#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS +#define STM32_DMA_FCR_DMDIS DMA_SxFCR_DMDIS +#define STM32_DMA_FCR_FTH_MASK DMA_SxFCR_FTH +#define STM32_DMA_FCR_FTH_1Q 0 +#define STM32_DMA_FCR_FTH_HALF DMA_SxFCR_FTH_0 +#define STM32_DMA_FCR_FTH_3Q DMA_SxFCR_FTH_1 +#define STM32_DMA_FCR_FTH_FULL (DMA_SxFCR_FTH_0 | DMA_SxFCR_FTH_1) +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + */ +#define STM32_DMA_ISR_FEIF DMA_LISR_FEIF0 +#define STM32_DMA_ISR_DMEIF DMA_LISR_DMEIF0 +#define STM32_DMA_ISR_TEIF DMA_LISR_TEIF0 +#define STM32_DMA_ISR_HTIF DMA_LISR_HTIF0 +#define STM32_DMA_ISR_TCIF DMA_LISR_TCIF0 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_DMA_SUPPORTS_DMAMUX) +#error "STM32_DMA_SUPPORTS_DMAMUX not defined in registry" +#endif + +#if !defined(STM32_HAS_DMA1) +#error "STM32_HAS_DMA1 missing in registry" +#endif + +#if !defined(STM32_HAS_DMA2) +#error "STM32_HAS_DMA2 missing in registry" +#endif + +#if !defined(STM32_DMA1_CH0_HANDLER) +#error "STM32_DMA1_CH0_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH1_HANDLER) +#error "STM32_DMA1_CH1_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH2_HANDLER) +#error "STM32_DMA1_CH2_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH3_HANDLER) +#error "STM32_DMA1_CH3_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH4_HANDLER) +#error "STM32_DMA1_CH4_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH5_HANDLER) +#error "STM32_DMA1_CH5_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH6_HANDLER) +#error "STM32_DMA1_CH6_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH7_HANDLER) +#error "STM32_DMA1_CH7_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH0_HANDLER) +#error "STM32_DMA2_CH0_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH1_HANDLER) +#error "STM32_DMA2_CH1_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH2_HANDLER) +#error "STM32_DMA2_CH2_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH3_HANDLER) +#error "STM32_DMA2_CH3_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH4_HANDLER) +#error "STM32_DMA2_CH4_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH5_HANDLER) +#error "STM32_DMA2_CH5_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH6_HANDLER) +#error "STM32_DMA2_CH6_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH7_HANDLER) +#error "STM32_DMA2_CH7_HANDLER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH0_NUMBER) +#error "STM32_DMA1_CH0_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH1_NUMBER) +#error "STM32_DMA1_CH1_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH2_NUMBER) +#error "STM32_DMA1_CH2_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH3_NUMBER) +#error "STM32_DMA1_CH3_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH4_NUMBER) +#error "STM32_DMA1_CH4_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH5_NUMBER) +#error "STM32_DMA1_CH5_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH6_NUMBER) +#error "STM32_DMA1_CH6_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA1_CH7_NUMBER) +#error "STM32_DMA1_CH7_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH0_NUMBER) +#error "STM32_DMA2_CH0_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH1_NUMBER) +#error "STM32_DMA2_CH1_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH2_NUMBER) +#error "STM32_DMA2_CH2_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH3_NUMBER) +#error "STM32_DMA2_CH3_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH4_NUMBER) +#error "STM32_DMA2_CH4_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH5_NUMBER) +#error "STM32_DMA2_CH5_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH6_NUMBER) +#error "STM32_DMA2_CH6_NUMBER missing in registry" +#endif + +#if !defined(STM32_DMA2_CH7_NUMBER) +#error "STM32_DMA2_CH7_NUMBER missing in registry" +#endif + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) +#include "stm32_dmamux.h" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the xISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); + +/** + * @brief STM32 DMA stream descriptor structure. + */ +typedef struct { + DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */ + volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__) + DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */ +#else + uint8_t dummy; /**< @brief Filler. */ +#endif + uint8_t shift; /**< @brief Bits offset in xIFCR + register. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_dma_stream_t; + +/*===========================================================================*/ +/* 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 dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the PAR register + * + * @special + */ +#define dmaStreamSetPeripheral(dmastp, addr) { \ + (dmastp)->stream->PAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the M0AR register + * + * @special + */ +#define dmaStreamSetMemory0(dmastp, addr) { \ + (dmastp)->stream->M0AR = (uint32_t)(addr); \ +} + +/** + * @brief Associates an alternate memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the M1AR register + * + * @special + */ +#define dmaStreamSetMemory1(dmastp, addr) { \ + (dmastp)->stream->M1AR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define dmaStreamSetTransactionSize(dmastp, size) { \ + (dmastp)->stream->NDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->stream->NDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CR register + * + * @special + */ +#define dmaStreamSetMode(dmastp, mode) { \ + (dmastp)->stream->CR = (uint32_t)(mode); \ +} + +/** + * @brief Programs the stream FIFO settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the FCR register + * + * @special + */ +#define dmaStreamSetFIFO(dmastp, mode) { \ + (dmastp)->stream->FCR = (uint32_t)(mode); \ +} + +/** + * @brief DMA stream enable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamEnable(dmastp) { \ + (dmastp)->stream->CR |= STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream disable. + * @details The function disables the specified stream, waits for the disable + * operation to complete and then clears any pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamDisable(dmastp) { \ + (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE | \ + STM32_DMA_CR_EN); \ + while (((dmastp)->stream->CR & STM32_DMA_CR_EN) != 0) \ + ; \ + dmaStreamClearInterrupt(dmastp); \ +} + +/** + * @brief DMA stream interrupt sources clear. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamClearInterrupt(dmastp) { \ + *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->shift; \ +} + +/** + * @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 dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @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); \ + dmaStreamEnable(dmastp); \ +} + +/** + * @brief Polled wait for DMA transfer end. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + */ +#define dmaWaitCompletion(dmastp) { \ + (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE); \ + while ((dmastp)->stream->CR & STM32_DMA_CR_EN) \ + ; \ + dmaStreamClearInterrupt(dmastp); \ +} + +/** + * @brief DMA stream current target. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAlloc(). + * @post After use the stream can be released using @p dmaStreamFree(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return Current memory target index. + * + * @special + */ +#define dmaStreamGetCurrentTarget(dmastp) \ + (((dmastp)->stream->CR >> DMA_SxCR_CT_Pos) & 1U) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dmaInit(void); + const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + void dmaStreamFreeI(const stm32_dma_stream_t *dmastp); + void dmaStreamFree(const stm32_dma_stream_t *dmastp); +#if STM32_DMA_SUPPORTS_DMAMUX == TRUE + void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMA_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/EXTIv1/driver.mk b/os/hal/ports/STM32/LLD/EXTIv1/driver.mk index 63016f9d78..ffa86453bc 100644 --- a/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +++ b/os/hal/ports/STM32/LLD/EXTIv1/driver.mk @@ -1,2 +1,2 @@ -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1 diff --git a/os/hal/ports/STM32/LLD/EXTIv1/notes.txt b/os/hal/ports/STM32/LLD/EXTIv1/notes.txt index 0083d86ea2..a74c93e7c6 100644 --- a/os/hal/ports/STM32/LLD/EXTIv1/notes.txt +++ b/os/hal/ports/STM32/LLD/EXTIv1/notes.txt @@ -1,16 +1,16 @@ -STM32 EXTIv1 driver. - -Driver capability: - -- Support for the EXTI peripheral. - -The file registry must export: - -STM32_EXTI_HAS_GROUP2 - True if lines from 32 to 63 are present. -STM32_EXTI_SEPARATE_RF - True if EXTI has separate status registers - for falling and raising edges. -STM32_EXTI_IMR1_MASK - Mask of the fixed lines that must not be - configured by the driver (0..31). -STM32_EXTI_IMR2_MASK - Mask of the fixed lines that must not be - configured by the driver (32..63). Only required - if STM32_EXTI_NUM_LINES is greater than 32. +STM32 EXTIv1 driver. + +Driver capability: + +- Support for the EXTI peripheral. + +The file registry must export: + +STM32_EXTI_HAS_GROUP2 - True if lines from 32 to 63 are present. +STM32_EXTI_SEPARATE_RF - True if EXTI has separate status registers + for falling and raising edges. +STM32_EXTI_IMR1_MASK - Mask of the fixed lines that must not be + configured by the driver (0..31). +STM32_EXTI_IMR2_MASK - Mask of the fixed lines that must not be + configured by the driver (32..63). Only required + if STM32_EXTI_NUM_LINES is greater than 32. diff --git a/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c b/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c index ba972f7739..79a01ebef6 100644 --- a/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c +++ b/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c @@ -1,218 +1,218 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file EXTIv1/stm32_exti.c - * @brief EXTI helper driver code. - * - * @addtogroup STM32_EXTI - * @details EXTI sharing helper driver. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring EXTI services - has been enabled.*/ -#if defined(STM32_EXTI_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 EXTI group 1 lines initialization. - * - * @param[in] mask mask of group 1 lines to be initialized - * @param[in] mode initialization mode - * - * @api - */ -void extiEnableGroup1(uint32_t mask, extimode_t mode) { - uint32_t cmask; - - /* Mask including only configurable lines.*/ - cmask = mask & ~STM32_EXTI_IMR1_MASK; - - if ((mode & EXTI_MODE_EDGES_MASK) == 0U) { - /* Disabling channels.*/ - EXTI->IMR1 &= ~mask; - EXTI->EMR1 &= ~mask; - EXTI->RTSR1 &= ~cmask; - EXTI->FTSR1 &= ~cmask; -#if STM32_EXTI_SEPARATE_RF == FALSE - EXTI->PR1 = cmask; -#else - EXTI->RPR1 = cmask; - EXTI->FPR1 = cmask; -#endif - } - else { - /* Programming edge registers.*/ - if (mode & EXTI_MODE_RISING_EDGE) { - EXTI->RTSR1 |= cmask; - } - else { - EXTI->RTSR1 &= ~cmask; - } - if (mode & EXTI_MODE_FALLING_EDGE) { - EXTI->FTSR1 |= cmask; - } - else { - EXTI->FTSR1 &= ~cmask; - } - - /* Programming interrupt and event registers.*/ - if ((mode & EXTI_MODE_ACTION_MASK) == EXTI_MODE_ACTION_INTERRUPT) { - EXTI->IMR1 |= mask; - EXTI->EMR1 &= ~mask; - } - else { - EXTI->EMR1 |= mask; - EXTI->IMR1 &= ~mask; - } - } -} - -#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) -/** - * @brief STM32 EXTI group 2 lines initialization. - * - * @param[in] mask mask of group 2 lines to be initialized - * @param[in] mode initialization mode - * - * @api - */ -void extiEnableGroup2(uint32_t mask, extimode_t mode) { - uint32_t cmask; - - /* Mask including only configurable lines.*/ - cmask = mask & ~STM32_EXTI_IMR2_MASK; - - if ((mode & EXTI_MODE_EDGES_MASK) == 0U) { - /* Disabling channels.*/ - EXTI->IMR2 &= ~mask; - EXTI->EMR2 &= ~mask; - EXTI->RTSR2 &= ~cmask; - EXTI->FTSR2 &= ~cmask; -#if STM32_EXTI_SEPARATE_RF == FALSE - EXTI->PR2 = cmask; -#else - EXTI->RPR2 = cmask; - EXTI->FPR2 = cmask; -#endif - } - else { - /* Programming edge registers.*/ - if (mode & EXTI_MODE_RISING_EDGE) { - EXTI->RTSR2 |= cmask; - } - else { - EXTI->RTSR2 &= ~cmask; - } - if (mode & EXTI_MODE_FALLING_EDGE) { - EXTI->FTSR2 |= cmask; - } - else { - EXTI->FTSR2 &= ~cmask; - } - - /* Programming interrupt and event registers.*/ - if ((mode & EXTI_MODE_ACTION_MASK) == EXTI_MODE_ACTION_INTERRUPT) { - EXTI->IMR2 |= mask; - EXTI->EMR2 &= ~mask; - } - else { - EXTI->EMR2 |= mask; - EXTI->IMR2 &= ~mask; - } - } -} -#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ - -/** - * @brief STM32 EXTI line initialization. - * - * @param[in] line line to be initialized - * @param[in] mode initialization mode - * - * @api - */ -void extiEnableLine(extiline_t line, extimode_t mode) { - uint32_t mask = (1U << (line & 0x1FU)); - - osalDbgCheck(line < STM32_EXTI_NUM_LINES); - osalDbgCheck((mode & ~EXTI_MODE_MASK) == 0U); - -#if STM32_EXTI_HAS_GROUP2 == TRUE - if (line < 32) { -#endif - extiEnableGroup1(mask, mode); -#if STM32_EXTI_HAS_GROUP2 == TRUE - } - else { - extiEnableGroup2(mask, mode); - } -#endif -} - -/** - * @brief STM32 EXTI line IRQ status clearing. - * - * @param[in] line line to be initialized - * - * @api - */ -void extiClearLine(extiline_t line) { - uint32_t mask = (1U << (line & 0x1FU)); - - osalDbgCheck(line < STM32_EXTI_NUM_LINES); - -#if STM32_EXTI_HAS_GROUP2 == TRUE - if (line < 32) { -#endif - extiClearGroup1(mask); -#if STM32_EXTI_HAS_GROUP2 == TRUE - } - else { - extiClearGroup2(mask); - } -#endif -} - -#endif /* STM32_EXTI_REQUIRED */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file EXTIv1/stm32_exti.c + * @brief EXTI helper driver code. + * + * @addtogroup STM32_EXTI + * @details EXTI sharing helper driver. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring EXTI services + has been enabled.*/ +#if defined(STM32_EXTI_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 EXTI group 1 lines initialization. + * + * @param[in] mask mask of group 1 lines to be initialized + * @param[in] mode initialization mode + * + * @api + */ +void extiEnableGroup1(uint32_t mask, extimode_t mode) { + uint32_t cmask; + + /* Mask including only configurable lines.*/ + cmask = mask & ~STM32_EXTI_IMR1_MASK; + + if ((mode & EXTI_MODE_EDGES_MASK) == 0U) { + /* Disabling channels.*/ + EXTI->IMR1 &= ~mask; + EXTI->EMR1 &= ~mask; + EXTI->RTSR1 &= ~cmask; + EXTI->FTSR1 &= ~cmask; +#if STM32_EXTI_SEPARATE_RF == FALSE + EXTI->PR1 = cmask; +#else + EXTI->RPR1 = cmask; + EXTI->FPR1 = cmask; +#endif + } + else { + /* Programming edge registers.*/ + if (mode & EXTI_MODE_RISING_EDGE) { + EXTI->RTSR1 |= cmask; + } + else { + EXTI->RTSR1 &= ~cmask; + } + if (mode & EXTI_MODE_FALLING_EDGE) { + EXTI->FTSR1 |= cmask; + } + else { + EXTI->FTSR1 &= ~cmask; + } + + /* Programming interrupt and event registers.*/ + if ((mode & EXTI_MODE_ACTION_MASK) == EXTI_MODE_ACTION_INTERRUPT) { + EXTI->IMR1 |= mask; + EXTI->EMR1 &= ~mask; + } + else { + EXTI->EMR1 |= mask; + EXTI->IMR1 &= ~mask; + } + } +} + +#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) +/** + * @brief STM32 EXTI group 2 lines initialization. + * + * @param[in] mask mask of group 2 lines to be initialized + * @param[in] mode initialization mode + * + * @api + */ +void extiEnableGroup2(uint32_t mask, extimode_t mode) { + uint32_t cmask; + + /* Mask including only configurable lines.*/ + cmask = mask & ~STM32_EXTI_IMR2_MASK; + + if ((mode & EXTI_MODE_EDGES_MASK) == 0U) { + /* Disabling channels.*/ + EXTI->IMR2 &= ~mask; + EXTI->EMR2 &= ~mask; + EXTI->RTSR2 &= ~cmask; + EXTI->FTSR2 &= ~cmask; +#if STM32_EXTI_SEPARATE_RF == FALSE + EXTI->PR2 = cmask; +#else + EXTI->RPR2 = cmask; + EXTI->FPR2 = cmask; +#endif + } + else { + /* Programming edge registers.*/ + if (mode & EXTI_MODE_RISING_EDGE) { + EXTI->RTSR2 |= cmask; + } + else { + EXTI->RTSR2 &= ~cmask; + } + if (mode & EXTI_MODE_FALLING_EDGE) { + EXTI->FTSR2 |= cmask; + } + else { + EXTI->FTSR2 &= ~cmask; + } + + /* Programming interrupt and event registers.*/ + if ((mode & EXTI_MODE_ACTION_MASK) == EXTI_MODE_ACTION_INTERRUPT) { + EXTI->IMR2 |= mask; + EXTI->EMR2 &= ~mask; + } + else { + EXTI->EMR2 |= mask; + EXTI->IMR2 &= ~mask; + } + } +} +#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ + +/** + * @brief STM32 EXTI line initialization. + * + * @param[in] line line to be initialized + * @param[in] mode initialization mode + * + * @api + */ +void extiEnableLine(extiline_t line, extimode_t mode) { + uint32_t mask = (1U << (line & 0x1FU)); + + osalDbgCheck(line < STM32_EXTI_NUM_LINES); + osalDbgCheck((mode & ~EXTI_MODE_MASK) == 0U); + +#if STM32_EXTI_HAS_GROUP2 == TRUE + if (line < 32) { +#endif + extiEnableGroup1(mask, mode); +#if STM32_EXTI_HAS_GROUP2 == TRUE + } + else { + extiEnableGroup2(mask, mode); + } +#endif +} + +/** + * @brief STM32 EXTI line IRQ status clearing. + * + * @param[in] line line to be initialized + * + * @api + */ +void extiClearLine(extiline_t line) { + uint32_t mask = (1U << (line & 0x1FU)); + + osalDbgCheck(line < STM32_EXTI_NUM_LINES); + +#if STM32_EXTI_HAS_GROUP2 == TRUE + if (line < 32) { +#endif + extiClearGroup1(mask); +#if STM32_EXTI_HAS_GROUP2 == TRUE + } + else { + extiClearGroup2(mask); + } +#endif +} + +#endif /* STM32_EXTI_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h b/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h index dadc58c508..a53813739b 100644 --- a/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h +++ b/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h @@ -1,257 +1,257 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file EXTIv1/stm32_exti.h - * @brief EXTI helper driver header. - * - * @addtogroup STM32_EXTI - * @{ - */ - -#ifndef STM32_EXTI_H -#define STM32_EXTI_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name EXTI channel modes - * @{ - */ -#define EXTI_MODE_MASK 7U /**< @brief Mode parameter mask. */ -#define EXTI_MODE_EDGES_MASK 3U /**< @brief Edges field mask. */ -#define EXTI_MODE_DISABLED 0U /**< @brief Channel disabled. */ -#define EXTI_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */ -#define EXTI_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */ -#define EXTI_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */ -#define EXTI_MODE_ACTION_MASK 4U /**< @brief Action field mask. */ -#define EXTI_MODE_ACTION_INTERRUPT 0U /**< @brief Interrupt mode. */ -#define EXTI_MODE_ACTION_EVENT 4U /**< @brief Event mode. */ -/** @} */ - -/* Handling differences in ST headers.*/ -#if !defined(STM32H7XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) && \ - !defined(STM32G0XX) && !defined(STM32G4XX) -#define EMR1 EMR -#define IMR1 IMR -#define PR1 PR -#define RTSR1 RTSR -#define FTSR1 FTSR -#endif - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_EXTI_NUM_LINES) -#error "STM32_EXTI_NUM_LINES not defined in registry" -#endif - -/* Checking for presence of bank 2 registers. If the definition is not - present in registry then it is inferred by the number of channels (which - is not an always-good method, see G0.*/ -#if !defined(STM32_EXTI_HAS_GROUP2) -#if STM32_EXTI_NUM_LINES <= 32 -#define STM32_EXTI_HAS_GROUP2 FALSE -#else -#define STM32_EXTI_HAS_GROUP2 TRUE -#endif -#endif /* !defined(STM32_EXTI_HAS_GROUP2) */ - -/* Determines if EXTI has dedicated CR register or if it is done in - SYSCFG (old style).*/ -#if !defined(STM32_EXTI_HAS_CR) -#define STM32_EXTI_HAS_CR FALSE -#endif - -/* Determines if EXTI has dedicated separate registers for raising and - falling edges.*/ -#if !defined(STM32_EXTI_SEPARATE_RF) -#define STM32_EXTI_SEPARATE_RF FALSE -#endif - -#if (STM32_EXTI_NUM_LINES < 0) || (STM32_EXTI_NUM_LINES > 63) -#error "invalid STM32_EXTI_NUM_LINES value" -#endif - -#if !defined(STM32_EXTI_IMR1_MASK) -#error "STM32_EXTI_IMR1_MASK not defined in registry" -#endif - -#if STM32_EXTI_NUM_LINES > 32 -#if !defined(STM32_EXTI_IMR2_MASK) -#error "STM32_EXTI_IMR2_MASK not defined in registry" -#endif -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an EXTI line identifier. - */ -typedef uint32_t extiline_t; - -/** - * @brief Type of an EXTI line mode. - */ -typedef uint32_t extimode_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief From group 1 line number to mask. - * - * @param[in] line line number in range 0..31 - */ -#define EXTI_MASK1(line) (uint32_t)(1U << (line)) - -/** - * @brief From group 2 line number to mask. - * - * @param[in] line line number in range 32..63 - */ -#define EXTI_MASK2(line) (uint32_t)(1U << ((line) - 32U)) - -/** - * @brief STM32 EXTI group 1 IRQ status clearing. - * - * @param[in] mask mask of group 1 lines to be initialized - * - * @special - */ -#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) -#define extiClearGroup1(mask) do { \ - osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines"); \ - EXTI->PR1 = (uint32_t)(mask); \ -} while (false) -#else -#define extiClearGroup1(mask) do { \ - osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines"); \ - EXTI->RPR1 = (uint32_t)(mask); \ - EXTI->FPR1 = (uint32_t)(mask); \ -} while (false) -#endif - -#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) -/** - * @brief STM32 EXTI group 2 IRQ status clearing. - * - * @param[in] mask mask of group 2 lines to be initialized - * - * @special - */ -#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) -#define extiClearGroup2(mask) do { \ - osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines"); \ - EXTI->PR2 = (uint32_t)(mask); \ -} while (false) -#else -#define extiClearGroup2(mask) do { \ - osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines"); \ - EXTI->RPR2 = (uint32_t)(mask); \ - EXTI->FPR2 = (uint32_t)(mask); \ -} while (false) -#endif -#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ - -/** - * @brief Serves an EXTI interrupt in group 1. - * - * @param[in] mask mask of lines to be cleared - * @param[out] out mask of lines needing processing - * - * @special - */ -#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) -#define extiGetAndClearGroup1(mask, out) do { \ - uint32_t pr1; \ - \ - pr1 = EXTI->PR1 & (mask); \ - (out) = pr1; \ - EXTI->PR1 = pr1; \ -} while (false) -#else -#define extiGetAndClearGroup1(mask, out) do { \ - uint32_t rpr1, fpr1; \ - \ - rpr1 = EXTI->RPR1 & (mask); \ - fpr1 = EXTI->FPR1 & (mask); \ - (out) = rpr1 | fpr1; \ - EXTI->RPR1 = rpr1; \ - EXTI->FPR1 = fpr1; \ -} while (false) -#endif - -#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) -/** - * @brief Serves an EXTI interrupt in group 2. - * - * @param[in] mask mask of lines to be cleared - * @param[out] out mask of lines needing processing - * - * @special - */ -#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) -#define extiGetAndClearGroup2(mask, out) do { \ - uint32_t pr2; \ - \ - pr2 = EXTI->PR2 & (mask); \ - (out) = pr2; \ - EXTI->PR2 = pr2; \ -} while (false) -#else -#define extiGetAndClearGroup2(mask, out) do { \ - uint32_t rpr2, fpr2; \ - \ - rpr2 = EXTI->RPR2 & (mask); \ - fpr2 = EXTI->FPR2 & (mask); \ - (out) = rpr2 | fpr2; \ - EXTI->RPR2 = rpr2; \ - EXTI->FPR2 = fpr2; \ -} while (false) -#endif -#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void extiEnableGroup1(uint32_t mask, extimode_t mode); -#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) - void extiEnableGroup2(uint32_t mask, extimode_t mode); -#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ - void extiEnableLine(extiline_t line, extimode_t mode); - void extiClearLine(extiline_t line); - #ifdef __cplusplus -} -#endif - -#endif /* STM32_EXTI_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file EXTIv1/stm32_exti.h + * @brief EXTI helper driver header. + * + * @addtogroup STM32_EXTI + * @{ + */ + +#ifndef STM32_EXTI_H +#define STM32_EXTI_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name EXTI channel modes + * @{ + */ +#define EXTI_MODE_MASK 7U /**< @brief Mode parameter mask. */ +#define EXTI_MODE_EDGES_MASK 3U /**< @brief Edges field mask. */ +#define EXTI_MODE_DISABLED 0U /**< @brief Channel disabled. */ +#define EXTI_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */ +#define EXTI_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */ +#define EXTI_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */ +#define EXTI_MODE_ACTION_MASK 4U /**< @brief Action field mask. */ +#define EXTI_MODE_ACTION_INTERRUPT 0U /**< @brief Interrupt mode. */ +#define EXTI_MODE_ACTION_EVENT 4U /**< @brief Event mode. */ +/** @} */ + +/* Handling differences in ST headers.*/ +#if !defined(STM32H7XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) && \ + !defined(STM32G0XX) && !defined(STM32G4XX) +#define EMR1 EMR +#define IMR1 IMR +#define PR1 PR +#define RTSR1 RTSR +#define FTSR1 FTSR +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_EXTI_NUM_LINES) +#error "STM32_EXTI_NUM_LINES not defined in registry" +#endif + +/* Checking for presence of bank 2 registers. If the definition is not + present in registry then it is inferred by the number of channels (which + is not an always-good method, see G0.*/ +#if !defined(STM32_EXTI_HAS_GROUP2) +#if STM32_EXTI_NUM_LINES <= 32 +#define STM32_EXTI_HAS_GROUP2 FALSE +#else +#define STM32_EXTI_HAS_GROUP2 TRUE +#endif +#endif /* !defined(STM32_EXTI_HAS_GROUP2) */ + +/* Determines if EXTI has dedicated CR register or if it is done in + SYSCFG (old style).*/ +#if !defined(STM32_EXTI_HAS_CR) +#define STM32_EXTI_HAS_CR FALSE +#endif + +/* Determines if EXTI has dedicated separate registers for raising and + falling edges.*/ +#if !defined(STM32_EXTI_SEPARATE_RF) +#define STM32_EXTI_SEPARATE_RF FALSE +#endif + +#if (STM32_EXTI_NUM_LINES < 0) || (STM32_EXTI_NUM_LINES > 63) +#error "invalid STM32_EXTI_NUM_LINES value" +#endif + +#if !defined(STM32_EXTI_IMR1_MASK) +#error "STM32_EXTI_IMR1_MASK not defined in registry" +#endif + +#if STM32_EXTI_NUM_LINES > 32 +#if !defined(STM32_EXTI_IMR2_MASK) +#error "STM32_EXTI_IMR2_MASK not defined in registry" +#endif +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an EXTI line identifier. + */ +typedef uint32_t extiline_t; + +/** + * @brief Type of an EXTI line mode. + */ +typedef uint32_t extimode_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief From group 1 line number to mask. + * + * @param[in] line line number in range 0..31 + */ +#define EXTI_MASK1(line) (uint32_t)(1U << (line)) + +/** + * @brief From group 2 line number to mask. + * + * @param[in] line line number in range 32..63 + */ +#define EXTI_MASK2(line) (uint32_t)(1U << ((line) - 32U)) + +/** + * @brief STM32 EXTI group 1 IRQ status clearing. + * + * @param[in] mask mask of group 1 lines to be initialized + * + * @special + */ +#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) +#define extiClearGroup1(mask) do { \ + osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines"); \ + EXTI->PR1 = (uint32_t)(mask); \ +} while (false) +#else +#define extiClearGroup1(mask) do { \ + osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines"); \ + EXTI->RPR1 = (uint32_t)(mask); \ + EXTI->FPR1 = (uint32_t)(mask); \ +} while (false) +#endif + +#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) +/** + * @brief STM32 EXTI group 2 IRQ status clearing. + * + * @param[in] mask mask of group 2 lines to be initialized + * + * @special + */ +#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) +#define extiClearGroup2(mask) do { \ + osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines"); \ + EXTI->PR2 = (uint32_t)(mask); \ +} while (false) +#else +#define extiClearGroup2(mask) do { \ + osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines"); \ + EXTI->RPR2 = (uint32_t)(mask); \ + EXTI->FPR2 = (uint32_t)(mask); \ +} while (false) +#endif +#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ + +/** + * @brief Serves an EXTI interrupt in group 1. + * + * @param[in] mask mask of lines to be cleared + * @param[out] out mask of lines needing processing + * + * @special + */ +#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) +#define extiGetAndClearGroup1(mask, out) do { \ + uint32_t pr1; \ + \ + pr1 = EXTI->PR1 & (mask); \ + (out) = pr1; \ + EXTI->PR1 = pr1; \ +} while (false) +#else +#define extiGetAndClearGroup1(mask, out) do { \ + uint32_t rpr1, fpr1; \ + \ + rpr1 = EXTI->RPR1 & (mask); \ + fpr1 = EXTI->FPR1 & (mask); \ + (out) = rpr1 | fpr1; \ + EXTI->RPR1 = rpr1; \ + EXTI->FPR1 = fpr1; \ +} while (false) +#endif + +#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) +/** + * @brief Serves an EXTI interrupt in group 2. + * + * @param[in] mask mask of lines to be cleared + * @param[out] out mask of lines needing processing + * + * @special + */ +#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__) +#define extiGetAndClearGroup2(mask, out) do { \ + uint32_t pr2; \ + \ + pr2 = EXTI->PR2 & (mask); \ + (out) = pr2; \ + EXTI->PR2 = pr2; \ +} while (false) +#else +#define extiGetAndClearGroup2(mask, out) do { \ + uint32_t rpr2, fpr2; \ + \ + rpr2 = EXTI->RPR2 & (mask); \ + fpr2 = EXTI->FPR2 & (mask); \ + (out) = rpr2 | fpr2; \ + EXTI->RPR2 = rpr2; \ + EXTI->FPR2 = fpr2; \ +} while (false) +#endif +#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void extiEnableGroup1(uint32_t mask, extimode_t mode); +#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__) + void extiEnableGroup2(uint32_t mask, extimode_t mode); +#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */ + void extiEnableLine(extiline_t line, extimode_t mode); + void extiClearLine(extiline_t line); + #ifdef __cplusplus +} +#endif + +#endif /* STM32_EXTI_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/FDCANv1/driver.mk b/os/hal/ports/STM32/LLD/FDCANv1/driver.mk index 734c3a0205..b69138ba64 100644 --- a/os/hal/ports/STM32/LLD/FDCANv1/driver.mk +++ b/os/hal/ports/STM32/LLD/FDCANv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1 diff --git a/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c b/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c index b6b46ee070..4307f94172 100644 --- a/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c +++ b/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c @@ -1,608 +1,608 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file FDCANv1/hal_can_lld.c - * @brief STM32 CAN subsystem low level driver source. - * - * @addtogroup CAN - * @{ - */ - -#include "hal.h" - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* Filter Standard Element Size in bytes.*/ -#define SRAMCAN_FLS_SIZE (1U * 4U) - -/* Filter Extended Element Size in bytes.*/ -#define SRAMCAN_FLE_SIZE (2U * 4U) - -/* RX FIFO 0 Elements Size in bytes.*/ -#define SRAMCAN_RF0_SIZE (18U * 4U) - -/* RX FIFO 1 Elements Size in bytes.*/ -#define SRAMCAN_RF1_SIZE (18U * 4U) - -/* RX Buffer Size in bytes.*/ -#define SRAMCAN_RB_SIZE (18U * 4U) - -/* TX Event FIFO Elements Size in bytes.*/ -#define SRAMCAN_TEF_SIZE (2U * 4U) - -/* TX FIFO/Queue Elements Size in bytes.*/ -#define SRAMCAN_TB_SIZE (18U * 4U) - -/* Trigger Memory Size in bytes.*/ -#define SRAMCAN_TM_SIZE (2U * 4U) - -/* Filter List Standard Start Address.*/ -#define SRAMCAN_FLSSA ((uint32_t)0) - -/* Filter List Extended Start Address.*/ -#define SRAMCAN_FLESA ((uint32_t)(SRAMCAN_FLSSA + \ - (STM32_FDCAN_FLS_NBR * SRAMCAN_FLS_SIZE))) - -/* RX FIFO 0 Start Address.*/ -#define SRAMCAN_RF0SA ((uint32_t)(SRAMCAN_FLESA + \ - (STM32_FDCAN_FLE_NBR * SRAMCAN_FLE_SIZE))) - -/* RX FIFO 1 Start Address.*/ -#define SRAMCAN_RF1SA ((uint32_t)(SRAMCAN_RF0SA + \ - (STM32_FDCAN_RF0_NBR * SRAMCAN_RF0_SIZE))) - -/* RX Buffer Start Address.*/ -#define SRAMCAN_RBSA ((uint32_t)(SRAMCAN_RF1SA + \ - (STM32_FDCAN_RF1_NBR * SRAMCAN_RF1_SIZE))) - -/* TX Event FIFO Start Address.*/ -#define SRAMCAN_TEFSA ((uint32_t)(SRAMCAN_RBSA + \ - (STM32_FDCAN_RB_NBR * SRAMCAN_RB_SIZE))) - -/* TX Buffers Start Address.*/ -#define SRAMCAN_TBSA ((uint32_t)(SRAMCAN_TEFSA + \ - (STM32_FDCAN_TEF_NBR * SRAMCAN_TEF_SIZE))) - -/* Trigger Memory Start Address.*/ -#define SRAMCAN_TMSA ((uint32_t)(SRAMCAN_TBSA + \ - (STM32_FDCAN_TB_NBR * SRAMCAN_TB_SIZE))) - -/* Message RAM size.*/ -#define SRAMCAN_SIZE ((uint32_t)(SRAMCAN_TMSA + \ - (STM32_FDCAN_TM_NBR * SRAMCAN_TM_SIZE))) - - -#define TIMEOUT_INIT_MS 250U -#define TIMEOUT_CSA_MS 250U - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief CAN1 driver identifier.*/ -#if STM32_CAN_USE_FDCAN1 || defined(__DOXYGEN__) -CANDriver CAND1; -#endif - -/** @brief CAN2 driver identifier.*/ -#if STM32_CAN_USE_FDCAN2 || defined(__DOXYGEN__) -CANDriver CAND2; -#endif - -/** @brief CAN3 driver identifier.*/ -#if STM32_CAN_USE_FDCAN3 || defined(__DOXYGEN__) -CANDriver CAND3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint8_t dlc_to_bytes[] = { - 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, - 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U -}; - -static uint32_t canclk; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static bool fdcan_clock_stop(CANDriver *canp) { - systime_t start, end; - - /* Requesting clock stop then waiting for it to happen.*/ - canp->fdcan->CCCR |= FDCAN_CCCR_CSR; - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); - while ((canp->fdcan->CCCR & FDCAN_CCCR_CSA) == 0U) { - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return true; - } - osalThreadSleepS(1); - } - - return false; -} - -static bool fdcan_init_mode(CANDriver *canp) { - systime_t start, end; - - /* Going in initialization mode then waiting for it to happen.*/ - canp->fdcan->CCCR |= FDCAN_CCCR_INIT; - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); - while ((canp->fdcan->CCCR & FDCAN_CCCR_INIT) == 0U) { - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return true; - } - osalThreadSleepS(1); - } - - return false; -} - -static bool fdcan_active_mode(CANDriver *canp) { - systime_t start, end; - - /* Going in initialization mode then waiting for it to happen.*/ - canp->fdcan->CCCR &= ~FDCAN_CCCR_INIT; - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); - while ((canp->fdcan->CCCR & FDCAN_CCCR_INIT) != 0U) { - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return true; - } - osalThreadSleepS(1); - } - - return false; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level CAN driver initialization. - * - * @notapi - */ -void can_lld_init(void) { - - canclk = 0U; - - /* Unit reset.*/ - rccResetFDCAN(); - -#if STM32_CAN_USE_FDCAN1 - /* Driver initialization.*/ - canObjectInit(&CAND1); - CAND1.fdcan = FDCAN1; - CAND1.ram_base = (uint32_t *)(SRAMCAN_BASE + 0U * SRAMCAN_SIZE); -#endif - -#if STM32_CAN_USE_FDCAN2 - /* Driver initialization.*/ - canObjectInit(&CAND2); - CAND2.fdcan = FDCAN2; - CAND2.ram_base = (uint32_t *)(SRAMCAN_BASE + 1U * SRAMCAN_SIZE); -#endif - -#if STM32_CAN_USE_FDCAN3 - /* Driver initialization.*/ - canObjectInit(&CAND3); - CAND3.fdcan = FDCAN3; - CAND3.ram_base = (uint32_t *)(SRAMCAN_BASE + 2U * SRAMCAN_SIZE); -#endif -} - -/** - * @brief Configures and activates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * @return The operation result. - * @retval false if the operation succeeded. - * @retval true if the operation failed. - * - * @notapi - */ -bool can_lld_start(CANDriver *canp) { - - /* Clock activation.*/ - rccEnableFDCAN(true); - - /* If it is the first activation then performing some extra - initializations.*/ - if (canclk == 0U) { - for (uint32_t *wp = canp->ram_base; - wp < canp->ram_base + SRAMCAN_SIZE; - wp += 1U) { - *wp = (uint32_t)0U; - } - } - -#if STM32_CAN_USE_FDCAN1 - if (&CAND1 == canp) { - canclk |= 1U; - } -#endif - -#if STM32_CAN_USE_FDCAN2 - if (&CAND2 == canp) { - canclk |= 2U; - } -#endif - -#if STM32_CAN_USE_FDCAN3 - if (&CAND3 == canp) { - canclk |= 4U; - } -#endif - - /* Requesting clock stop.*/ - if (fdcan_clock_stop(canp)) { - osalDbgAssert(false, "CAN clock stop failed, check clocks and pin config"); - return true; - } - - /* Going in initialization mode.*/ - if (fdcan_init_mode(canp)) { - osalDbgAssert(false, "CAN initialization failed, check clocks and pin config"); - return true; - } - - /* Configuration can be performed now.*/ - canp->fdcan->CCCR |= FDCAN_CCCR_CCE; - canp->fdcan->CCCR &= ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA); - - /* Setting up operation mode except driver-controlled bits.*/ - canp->fdcan->NBTP = canp->config->NBTP; - canp->fdcan->DBTP = canp->config->DBTP; - canp->fdcan->CCCR |= canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA | - FDCAN_CCCR_CCE | FDCAN_CCCR_INIT); - canp->fdcan->TEST = canp->config->TEST; -#ifdef STM32G4XX - canp->fdcan->RXGFC = canp->config->RXGFC; -#elif defined(STM32H7XX) - canp->fdcan->GFC = canp->config->RXGFC; -#else -#error "Unsupported STM32 for FDCAN LLD driver" -#endif - - /* Enabling interrupts, only using interrupt zero.*/ - canp->fdcan->IR = (uint32_t)-1; - canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE | - FDCAN_IE_RF0NE | FDCAN_IE_RF0LE | - FDCAN_IE_TCE; - canp->fdcan->TXBTIE = FDCAN_TXBTIE_TIE; - canp->fdcan->ILE = FDCAN_ILE_EINT0; - -#ifdef STM32H7XX - /* H7 version of FDCAN has configurable memory layout, so configure it */ - canp->fdcan->SIDFC = STM32_FDCAN_FLS_NBR << 16 | SRAMCAN_FLSSA; - canp->fdcan->XIDFC = STM32_FDCAN_FLE_NBR << 16 | SRAMCAN_FLESA; - canp->fdcan->RXF0C = STM32_FDCAN_RF0_NBR << 16 | SRAMCAN_RF0SA; - canp->fdcan->RXF1C = STM32_FDCAN_RF1_NBR << 16 | SRAMCAN_RF1SA; - canp->fdcan->RXBC = SRAMCAN_RBSA; - canp->fdcan->TXEFC = STM32_FDCAN_TEF_NBR << 16 | SRAMCAN_TEFSA; - /* NB: this doesn't set NDTB, but sets TFQS to run in queue mode with no dedicated buffers */ - canp->fdcan->TXBC = STM32_FDCAN_TB_NBR << 24 | SRAMCAN_TBSA; - - /* set to use the full 18-byte size buffer elements */ - canp->fdcan->TXESC = 0x007; - canp->fdcan->RXESC = 0x777; -#endif /* STM32H7XX */ - - /* Going in active mode.*/ - if (fdcan_active_mode(canp)) { - osalDbgAssert(false, "CAN initialization failed, check clocks and pin config"); - return true; - } - - return false; -} - -/** - * @brief Deactivates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_stop(CANDriver *canp) { - - /* If in ready state then disables the CAN peripheral.*/ - if (canp->state == CAN_READY) { - /* Disabling and clearing interrupts.*/ - canp->fdcan->IE = 0U; - canp->fdcan->IR = (uint32_t)-1; - canp->fdcan->ILE = 0U; - canp->fdcan->TXBTIE = 0U; - - /* Disables the peripheral.*/ - (void) fdcan_clock_stop(canp); - -#if STM32_CAN_USE_FDCAN1 - if (&CAND1 == canp) { - canclk &= ~1U; - } -#endif - -#if STM32_CAN_USE_FDCAN2 - if (&CAND2 == canp) { - canclk &= ~2U; - } -#endif - -#if STM32_CAN_USE_FDCAN3 - if (&CAND3 == canp) { - canclk &= ~4U; - } -#endif - - if (canclk == 0U) { - rccDisableFDCAN(); - } - } -} - -/** - * @brief Determines whether a frame can be transmitted. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @return The queue space availability. - * @retval false no space in the transmit queue. - * @retval true transmit slot available. - * - * @notapi - */ -bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { - - (void)mailbox; - - return (bool)((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQF) == 0U); -} - -/** - * @brief Inserts a frame into the transmit queue. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] ctfp pointer to the CAN frame to be transmitted - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @notapi - */ -void can_lld_transmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) { - uint32_t put_index; - uint32_t *tx_address; - - (void)mailbox; - - osalDbgCheck(dlc_to_bytes[ctfp->DLC] <= CAN_MAX_DLC_BYTES); - - /* Retrieve the TX FIFO put index.*/ - put_index = ((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos); - - /* Writing frame.*/ - tx_address = canp->ram_base + - ((SRAMCAN_TBSA + (put_index * SRAMCAN_TB_SIZE)) / sizeof (uint32_t)); - - *tx_address++ = ctfp->header32[0]; - *tx_address++ = ctfp->header32[1]; - for (unsigned i = 0U; i < dlc_to_bytes[ctfp->DLC]; i += 4U) { - *tx_address++ = ctfp->data32[i / 4U]; - } - - /* Starting transmission.*/ - canp->fdcan->TXBAR = ((uint32_t)1 << put_index); -} - -/** - * @brief Determines whether a frame has been received. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @return The queue space availability. - * @retval false no space in the transmit queue. - * @retval true transmit slot available. - * - * @notapi - */ -bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { - - switch (mailbox) { - case CAN_ANY_MAILBOX: - return can_lld_is_rx_nonempty(canp, 1U) || - can_lld_is_rx_nonempty(canp, 2U); - case 1: - return (bool)((canp->fdcan->RXF0S & FDCAN_RXF0S_F0FL) != 0U); - case 2: - return (bool)((canp->fdcan->RXF1S & FDCAN_RXF1S_F1FL) != 0U); - default: - return false; - } -} - -/** - * @brief Receives a frame from the input queue. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[out] crfp pointer to the buffer where the CAN frame is copied - * - * @notapi - */ -void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) { - uint32_t get_index; - uint32_t *rx_address; - - if (mailbox == CAN_ANY_MAILBOX) { - if (can_lld_is_rx_nonempty(canp, 1U)) { - mailbox = 1U; - } - else if (can_lld_is_rx_nonempty(canp, 2U)) { - mailbox = 2U; - } - else { - return; - } - } - - if (mailbox == 1U) { - /* GET index RXF0, add it and the length to the rx_address.*/ - get_index = (canp->fdcan->RXF0S & FDCAN_RXF0S_F0GI_Msk) >> FDCAN_RXF0S_F0GI_Pos; - rx_address = canp->ram_base + (SRAMCAN_RF0SA + - (get_index * SRAMCAN_RF0_SIZE)) / sizeof (uint32_t); - } - else { - /* GET index RXF1, add it and the length to the rx_address.*/ - get_index = (canp->fdcan->RXF1S & FDCAN_RXF1S_F1GI_Msk) >> FDCAN_RXF1S_F1GI_Pos; - rx_address = canp->ram_base + (SRAMCAN_RF1SA + - (get_index * SRAMCAN_RF1_SIZE)) / sizeof (uint32_t); - } - crfp->header32[0] = *rx_address++; - crfp->header32[1] = *rx_address++; - - /* Copy message from FDCAN peripheral's SRAM to structure. RAM is restricted - to word aligned accesses, so up to 3 extra bytes may be copied.*/ - for (unsigned i = 0U; i < dlc_to_bytes[crfp->DLC]; i += 4U) { - crfp->data32[i / 4U] = *rx_address++; - } - - /* Acknowledge receipt by writing the get-index to the acknowledge - register RXFxA then re-enable RX FIFO message arrived interrupt once - the FIFO is emptied.*/ - if (mailbox == 1U) { - uint32_t rxf0a = canp->fdcan->RXF0A; - rxf0a &= ~FDCAN_RXF0A_F0AI_Msk; - rxf0a |= get_index << FDCAN_RXF0A_F0AI_Pos; - canp->fdcan->RXF0A = rxf0a; - - if (!can_lld_is_rx_nonempty(canp, mailbox)) { -// canp->fdcan->IR = FDCAN_IR_RF0N; - canp->fdcan->IE |= FDCAN_IE_RF0NE; - } - } - else { - uint32_t rxf1a = canp->fdcan->RXF1A; - rxf1a &= ~FDCAN_RXF1A_F1AI_Msk; - rxf1a |= get_index << FDCAN_RXF1A_F1AI_Pos; - canp->fdcan->RXF1A = rxf1a; - - if (!can_lld_is_rx_nonempty(canp, mailbox)) { -// canp->fdcan->IR = FDCAN_IR_RF1N; - canp->fdcan->IE |= FDCAN_IE_RF1NE; - } - } -} - -/** - * @brief Tries to abort an ongoing transmission. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number - * - * @notapi - */ -void can_lld_abort(CANDriver *canp, canmbx_t mailbox) { - - (void)canp; - (void)mailbox; -} - -#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) -/** - * @brief Enters the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_sleep(CANDriver *canp) { - - (void)canp; -} - -/** - * @brief Enforces leaving the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_wakeup(CANDriver *canp) { - - (void)canp; -} -#endif /* CAN_USE_SLEEP_MODE */ - -/** - * @brief FDCAN IRQ0 service routine. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_serve_interrupt(CANDriver *canp) { - uint32_t ir; - - /* Getting and clearing active IRQs.*/ - ir = canp->fdcan->IR; - canp->fdcan->IR = ir; - - /* RX events.*/ - if ((ir & FDCAN_IR_RF0N) != 0U) { - /* Disabling this source until the queue is emptied.*/ - canp->fdcan->IE &= ~FDCAN_IE_RF0NE; - _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(1U)); - } - if ((ir & FDCAN_IR_RF1N) != 0U) { - /* Disabling this source until the queue is emptied.*/ - canp->fdcan->IE &= ~FDCAN_IE_RF1NE; - _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(2U)); - } - - /* Overflow events.*/ - if (((ir & FDCAN_IR_RF0L) != 0U) || ((ir & FDCAN_IR_RF1L) != 0U) ) { - _can_error_isr(canp, CAN_OVERFLOW_ERROR); - } - - /* TX events.*/ - if ((ir & FDCAN_IR_TC) != 0U) { - eventflags_t flags = 0U; - - flags |= 1U; - _can_tx_empty_isr(canp, flags); - } -} - -#endif /* HAL_USE_CAN */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file FDCANv1/hal_can_lld.c + * @brief STM32 CAN subsystem low level driver source. + * + * @addtogroup CAN + * @{ + */ + +#include "hal.h" + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* Filter Standard Element Size in bytes.*/ +#define SRAMCAN_FLS_SIZE (1U * 4U) + +/* Filter Extended Element Size in bytes.*/ +#define SRAMCAN_FLE_SIZE (2U * 4U) + +/* RX FIFO 0 Elements Size in bytes.*/ +#define SRAMCAN_RF0_SIZE (18U * 4U) + +/* RX FIFO 1 Elements Size in bytes.*/ +#define SRAMCAN_RF1_SIZE (18U * 4U) + +/* RX Buffer Size in bytes.*/ +#define SRAMCAN_RB_SIZE (18U * 4U) + +/* TX Event FIFO Elements Size in bytes.*/ +#define SRAMCAN_TEF_SIZE (2U * 4U) + +/* TX FIFO/Queue Elements Size in bytes.*/ +#define SRAMCAN_TB_SIZE (18U * 4U) + +/* Trigger Memory Size in bytes.*/ +#define SRAMCAN_TM_SIZE (2U * 4U) + +/* Filter List Standard Start Address.*/ +#define SRAMCAN_FLSSA ((uint32_t)0) + +/* Filter List Extended Start Address.*/ +#define SRAMCAN_FLESA ((uint32_t)(SRAMCAN_FLSSA + \ + (STM32_FDCAN_FLS_NBR * SRAMCAN_FLS_SIZE))) + +/* RX FIFO 0 Start Address.*/ +#define SRAMCAN_RF0SA ((uint32_t)(SRAMCAN_FLESA + \ + (STM32_FDCAN_FLE_NBR * SRAMCAN_FLE_SIZE))) + +/* RX FIFO 1 Start Address.*/ +#define SRAMCAN_RF1SA ((uint32_t)(SRAMCAN_RF0SA + \ + (STM32_FDCAN_RF0_NBR * SRAMCAN_RF0_SIZE))) + +/* RX Buffer Start Address.*/ +#define SRAMCAN_RBSA ((uint32_t)(SRAMCAN_RF1SA + \ + (STM32_FDCAN_RF1_NBR * SRAMCAN_RF1_SIZE))) + +/* TX Event FIFO Start Address.*/ +#define SRAMCAN_TEFSA ((uint32_t)(SRAMCAN_RBSA + \ + (STM32_FDCAN_RB_NBR * SRAMCAN_RB_SIZE))) + +/* TX Buffers Start Address.*/ +#define SRAMCAN_TBSA ((uint32_t)(SRAMCAN_TEFSA + \ + (STM32_FDCAN_TEF_NBR * SRAMCAN_TEF_SIZE))) + +/* Trigger Memory Start Address.*/ +#define SRAMCAN_TMSA ((uint32_t)(SRAMCAN_TBSA + \ + (STM32_FDCAN_TB_NBR * SRAMCAN_TB_SIZE))) + +/* Message RAM size.*/ +#define SRAMCAN_SIZE ((uint32_t)(SRAMCAN_TMSA + \ + (STM32_FDCAN_TM_NBR * SRAMCAN_TM_SIZE))) + + +#define TIMEOUT_INIT_MS 250U +#define TIMEOUT_CSA_MS 250U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief CAN1 driver identifier.*/ +#if STM32_CAN_USE_FDCAN1 || defined(__DOXYGEN__) +CANDriver CAND1; +#endif + +/** @brief CAN2 driver identifier.*/ +#if STM32_CAN_USE_FDCAN2 || defined(__DOXYGEN__) +CANDriver CAND2; +#endif + +/** @brief CAN3 driver identifier.*/ +#if STM32_CAN_USE_FDCAN3 || defined(__DOXYGEN__) +CANDriver CAND3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint8_t dlc_to_bytes[] = { + 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, + 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U +}; + +static uint32_t canclk; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static bool fdcan_clock_stop(CANDriver *canp) { + systime_t start, end; + + /* Requesting clock stop then waiting for it to happen.*/ + canp->fdcan->CCCR |= FDCAN_CCCR_CSR; + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); + while ((canp->fdcan->CCCR & FDCAN_CCCR_CSA) == 0U) { + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return true; + } + osalThreadSleepS(1); + } + + return false; +} + +static bool fdcan_init_mode(CANDriver *canp) { + systime_t start, end; + + /* Going in initialization mode then waiting for it to happen.*/ + canp->fdcan->CCCR |= FDCAN_CCCR_INIT; + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); + while ((canp->fdcan->CCCR & FDCAN_CCCR_INIT) == 0U) { + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return true; + } + osalThreadSleepS(1); + } + + return false; +} + +static bool fdcan_active_mode(CANDriver *canp) { + systime_t start, end; + + /* Going in initialization mode then waiting for it to happen.*/ + canp->fdcan->CCCR &= ~FDCAN_CCCR_INIT; + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); + while ((canp->fdcan->CCCR & FDCAN_CCCR_INIT) != 0U) { + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return true; + } + osalThreadSleepS(1); + } + + return false; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level CAN driver initialization. + * + * @notapi + */ +void can_lld_init(void) { + + canclk = 0U; + + /* Unit reset.*/ + rccResetFDCAN(); + +#if STM32_CAN_USE_FDCAN1 + /* Driver initialization.*/ + canObjectInit(&CAND1); + CAND1.fdcan = FDCAN1; + CAND1.ram_base = (uint32_t *)(SRAMCAN_BASE + 0U * SRAMCAN_SIZE); +#endif + +#if STM32_CAN_USE_FDCAN2 + /* Driver initialization.*/ + canObjectInit(&CAND2); + CAND2.fdcan = FDCAN2; + CAND2.ram_base = (uint32_t *)(SRAMCAN_BASE + 1U * SRAMCAN_SIZE); +#endif + +#if STM32_CAN_USE_FDCAN3 + /* Driver initialization.*/ + canObjectInit(&CAND3); + CAND3.fdcan = FDCAN3; + CAND3.ram_base = (uint32_t *)(SRAMCAN_BASE + 2U * SRAMCAN_SIZE); +#endif +} + +/** + * @brief Configures and activates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * @return The operation result. + * @retval false if the operation succeeded. + * @retval true if the operation failed. + * + * @notapi + */ +bool can_lld_start(CANDriver *canp) { + + /* Clock activation.*/ + rccEnableFDCAN(true); + + /* If it is the first activation then performing some extra + initializations.*/ + if (canclk == 0U) { + for (uint32_t *wp = canp->ram_base; + wp < canp->ram_base + SRAMCAN_SIZE; + wp += 1U) { + *wp = (uint32_t)0U; + } + } + +#if STM32_CAN_USE_FDCAN1 + if (&CAND1 == canp) { + canclk |= 1U; + } +#endif + +#if STM32_CAN_USE_FDCAN2 + if (&CAND2 == canp) { + canclk |= 2U; + } +#endif + +#if STM32_CAN_USE_FDCAN3 + if (&CAND3 == canp) { + canclk |= 4U; + } +#endif + + /* Requesting clock stop.*/ + if (fdcan_clock_stop(canp)) { + osalDbgAssert(false, "CAN clock stop failed, check clocks and pin config"); + return true; + } + + /* Going in initialization mode.*/ + if (fdcan_init_mode(canp)) { + osalDbgAssert(false, "CAN initialization failed, check clocks and pin config"); + return true; + } + + /* Configuration can be performed now.*/ + canp->fdcan->CCCR |= FDCAN_CCCR_CCE; + canp->fdcan->CCCR &= ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA); + + /* Setting up operation mode except driver-controlled bits.*/ + canp->fdcan->NBTP = canp->config->NBTP; + canp->fdcan->DBTP = canp->config->DBTP; + canp->fdcan->CCCR |= canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA | + FDCAN_CCCR_CCE | FDCAN_CCCR_INIT); + canp->fdcan->TEST = canp->config->TEST; +#ifdef STM32G4XX + canp->fdcan->RXGFC = canp->config->RXGFC; +#elif defined(STM32H7XX) + canp->fdcan->GFC = canp->config->RXGFC; +#else +#error "Unsupported STM32 for FDCAN LLD driver" +#endif + + /* Enabling interrupts, only using interrupt zero.*/ + canp->fdcan->IR = (uint32_t)-1; + canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE | + FDCAN_IE_RF0NE | FDCAN_IE_RF0LE | + FDCAN_IE_TCE; + canp->fdcan->TXBTIE = FDCAN_TXBTIE_TIE; + canp->fdcan->ILE = FDCAN_ILE_EINT0; + +#ifdef STM32H7XX + /* H7 version of FDCAN has configurable memory layout, so configure it */ + canp->fdcan->SIDFC = STM32_FDCAN_FLS_NBR << 16 | SRAMCAN_FLSSA; + canp->fdcan->XIDFC = STM32_FDCAN_FLE_NBR << 16 | SRAMCAN_FLESA; + canp->fdcan->RXF0C = STM32_FDCAN_RF0_NBR << 16 | SRAMCAN_RF0SA; + canp->fdcan->RXF1C = STM32_FDCAN_RF1_NBR << 16 | SRAMCAN_RF1SA; + canp->fdcan->RXBC = SRAMCAN_RBSA; + canp->fdcan->TXEFC = STM32_FDCAN_TEF_NBR << 16 | SRAMCAN_TEFSA; + /* NB: this doesn't set NDTB, but sets TFQS to run in queue mode with no dedicated buffers */ + canp->fdcan->TXBC = STM32_FDCAN_TB_NBR << 24 | SRAMCAN_TBSA; + + /* set to use the full 18-byte size buffer elements */ + canp->fdcan->TXESC = 0x007; + canp->fdcan->RXESC = 0x777; +#endif /* STM32H7XX */ + + /* Going in active mode.*/ + if (fdcan_active_mode(canp)) { + osalDbgAssert(false, "CAN initialization failed, check clocks and pin config"); + return true; + } + + return false; +} + +/** + * @brief Deactivates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_stop(CANDriver *canp) { + + /* If in ready state then disables the CAN peripheral.*/ + if (canp->state == CAN_READY) { + /* Disabling and clearing interrupts.*/ + canp->fdcan->IE = 0U; + canp->fdcan->IR = (uint32_t)-1; + canp->fdcan->ILE = 0U; + canp->fdcan->TXBTIE = 0U; + + /* Disables the peripheral.*/ + (void) fdcan_clock_stop(canp); + +#if STM32_CAN_USE_FDCAN1 + if (&CAND1 == canp) { + canclk &= ~1U; + } +#endif + +#if STM32_CAN_USE_FDCAN2 + if (&CAND2 == canp) { + canclk &= ~2U; + } +#endif + +#if STM32_CAN_USE_FDCAN3 + if (&CAND3 == canp) { + canclk &= ~4U; + } +#endif + + if (canclk == 0U) { + rccDisableFDCAN(); + } + } +} + +/** + * @brief Determines whether a frame can be transmitted. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @return The queue space availability. + * @retval false no space in the transmit queue. + * @retval true transmit slot available. + * + * @notapi + */ +bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { + + (void)mailbox; + + return (bool)((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQF) == 0U); +} + +/** + * @brief Inserts a frame into the transmit queue. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] ctfp pointer to the CAN frame to be transmitted + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @notapi + */ +void can_lld_transmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) { + uint32_t put_index; + uint32_t *tx_address; + + (void)mailbox; + + osalDbgCheck(dlc_to_bytes[ctfp->DLC] <= CAN_MAX_DLC_BYTES); + + /* Retrieve the TX FIFO put index.*/ + put_index = ((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos); + + /* Writing frame.*/ + tx_address = canp->ram_base + + ((SRAMCAN_TBSA + (put_index * SRAMCAN_TB_SIZE)) / sizeof (uint32_t)); + + *tx_address++ = ctfp->header32[0]; + *tx_address++ = ctfp->header32[1]; + for (unsigned i = 0U; i < dlc_to_bytes[ctfp->DLC]; i += 4U) { + *tx_address++ = ctfp->data32[i / 4U]; + } + + /* Starting transmission.*/ + canp->fdcan->TXBAR = ((uint32_t)1 << put_index); +} + +/** + * @brief Determines whether a frame has been received. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @return The queue space availability. + * @retval false no space in the transmit queue. + * @retval true transmit slot available. + * + * @notapi + */ +bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { + + switch (mailbox) { + case CAN_ANY_MAILBOX: + return can_lld_is_rx_nonempty(canp, 1U) || + can_lld_is_rx_nonempty(canp, 2U); + case 1: + return (bool)((canp->fdcan->RXF0S & FDCAN_RXF0S_F0FL) != 0U); + case 2: + return (bool)((canp->fdcan->RXF1S & FDCAN_RXF1S_F1FL) != 0U); + default: + return false; + } +} + +/** + * @brief Receives a frame from the input queue. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[out] crfp pointer to the buffer where the CAN frame is copied + * + * @notapi + */ +void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) { + uint32_t get_index; + uint32_t *rx_address; + + if (mailbox == CAN_ANY_MAILBOX) { + if (can_lld_is_rx_nonempty(canp, 1U)) { + mailbox = 1U; + } + else if (can_lld_is_rx_nonempty(canp, 2U)) { + mailbox = 2U; + } + else { + return; + } + } + + if (mailbox == 1U) { + /* GET index RXF0, add it and the length to the rx_address.*/ + get_index = (canp->fdcan->RXF0S & FDCAN_RXF0S_F0GI_Msk) >> FDCAN_RXF0S_F0GI_Pos; + rx_address = canp->ram_base + (SRAMCAN_RF0SA + + (get_index * SRAMCAN_RF0_SIZE)) / sizeof (uint32_t); + } + else { + /* GET index RXF1, add it and the length to the rx_address.*/ + get_index = (canp->fdcan->RXF1S & FDCAN_RXF1S_F1GI_Msk) >> FDCAN_RXF1S_F1GI_Pos; + rx_address = canp->ram_base + (SRAMCAN_RF1SA + + (get_index * SRAMCAN_RF1_SIZE)) / sizeof (uint32_t); + } + crfp->header32[0] = *rx_address++; + crfp->header32[1] = *rx_address++; + + /* Copy message from FDCAN peripheral's SRAM to structure. RAM is restricted + to word aligned accesses, so up to 3 extra bytes may be copied.*/ + for (unsigned i = 0U; i < dlc_to_bytes[crfp->DLC]; i += 4U) { + crfp->data32[i / 4U] = *rx_address++; + } + + /* Acknowledge receipt by writing the get-index to the acknowledge + register RXFxA then re-enable RX FIFO message arrived interrupt once + the FIFO is emptied.*/ + if (mailbox == 1U) { + uint32_t rxf0a = canp->fdcan->RXF0A; + rxf0a &= ~FDCAN_RXF0A_F0AI_Msk; + rxf0a |= get_index << FDCAN_RXF0A_F0AI_Pos; + canp->fdcan->RXF0A = rxf0a; + + if (!can_lld_is_rx_nonempty(canp, mailbox)) { +// canp->fdcan->IR = FDCAN_IR_RF0N; + canp->fdcan->IE |= FDCAN_IE_RF0NE; + } + } + else { + uint32_t rxf1a = canp->fdcan->RXF1A; + rxf1a &= ~FDCAN_RXF1A_F1AI_Msk; + rxf1a |= get_index << FDCAN_RXF1A_F1AI_Pos; + canp->fdcan->RXF1A = rxf1a; + + if (!can_lld_is_rx_nonempty(canp, mailbox)) { +// canp->fdcan->IR = FDCAN_IR_RF1N; + canp->fdcan->IE |= FDCAN_IE_RF1NE; + } + } +} + +/** + * @brief Tries to abort an ongoing transmission. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number + * + * @notapi + */ +void can_lld_abort(CANDriver *canp, canmbx_t mailbox) { + + (void)canp; + (void)mailbox; +} + +#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) +/** + * @brief Enters the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_sleep(CANDriver *canp) { + + (void)canp; +} + +/** + * @brief Enforces leaving the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_wakeup(CANDriver *canp) { + + (void)canp; +} +#endif /* CAN_USE_SLEEP_MODE */ + +/** + * @brief FDCAN IRQ0 service routine. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_serve_interrupt(CANDriver *canp) { + uint32_t ir; + + /* Getting and clearing active IRQs.*/ + ir = canp->fdcan->IR; + canp->fdcan->IR = ir; + + /* RX events.*/ + if ((ir & FDCAN_IR_RF0N) != 0U) { + /* Disabling this source until the queue is emptied.*/ + canp->fdcan->IE &= ~FDCAN_IE_RF0NE; + _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(1U)); + } + if ((ir & FDCAN_IR_RF1N) != 0U) { + /* Disabling this source until the queue is emptied.*/ + canp->fdcan->IE &= ~FDCAN_IE_RF1NE; + _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(2U)); + } + + /* Overflow events.*/ + if (((ir & FDCAN_IR_RF0L) != 0U) || ((ir & FDCAN_IR_RF1L) != 0U) ) { + _can_error_isr(canp, CAN_OVERFLOW_ERROR); + } + + /* TX events.*/ + if ((ir & FDCAN_IR_TC) != 0U) { + eventflags_t flags = 0U; + + flags |= 1U; + _can_tx_empty_isr(canp, flags); + } +} + +#endif /* HAL_USE_CAN */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h b/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h index ede1e459ec..6c41dcef4b 100644 --- a/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h +++ b/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h @@ -1,490 +1,490 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file FDCANv1/hal_can_lld.h - * @brief STM32 CAN subsystem low level driver header. - * - * @addtogroup CAN - * @{ - */ - -#ifndef HAL_CAN_LLD_H -#define HAL_CAN_LLD_H - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Maximum number of bytes in data of CAN packets. - */ -#define CAN_MAX_DLC_BYTES 64 - -/** - * @brief Number of transmit mailboxes. - */ -#define CAN_TX_MAILBOXES 1 - -/** - * @brief Number of receive mailboxes. - */ -#define CAN_RX_MAILBOXES 2 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief CAN1 driver enable switch. - * @details If set to @p TRUE the support for FDCAN1 is included. - */ -#if !defined(STM32_CAN_USE_FDCAN1) || defined(__DOXYGEN__) -#define STM32_CAN_USE_FDCAN1 FALSE -#endif - -/** - * @brief CAN2 driver enable switch. - * @details If set to @p TRUE the support for FDCAN2 is included. - */ -#if !defined(STM32_CAN_USE_FDCAN2) || defined(__DOXYGEN__) -#define STM32_CAN_USE_FDCAN2 FALSE -#endif - -/** - * @brief CAN3 driver enable switch. - * @details If set to @p TRUE the support for FDCAN3 is included. - */ -#if !defined(STM32_CAN_USE_FDCAN3) || defined(__DOXYGEN__) -#define STM32_CAN_USE_FDCAN3 FALSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_FDCAN1) -#error "STM32_HAS_FDCAN1 not defined in registry" -#endif - -#if !defined(STM32_HAS_FDCAN2) -#error "STM32_HAS_FDCAN2 not defined in registry" -#endif - -#if !defined(STM32_HAS_FDCAN3) -#error "STM32_HAS_FDCAN3 not defined in registry" -#endif - -#if STM32_CAN_USE_FDCAN1 && !STM32_HAS_FDCAN1 -#error "FDCAN1 not present in the selected device" -#endif - -#if STM32_CAN_USE_FDCAN2 && !STM32_HAS_FDCAN2 -#error "FDCAN2 not present in the selected device" -#endif - -#if STM32_CAN_USE_FDCAN3 && !STM32_HAS_FDCAN3 -#error "FDCAN3 not present in the selected device" -#endif - -#if !STM32_CAN_USE_FDCAN1 && !STM32_CAN_USE_FDCAN2 && !STM32_CAN_USE_FDCAN3 -#error "CAN driver activated but no FDCAN peripheral assigned" -#endif - -#if !defined(STM32_FDCAN_FLS_NBR) -#error "STM32_FDCAN_FLS_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_FLE_NBR) -#error "STM32_FDCAN_FLE_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_RF0_NBR) -#error "STM32_FDCAN_RF0_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_RF1_NBR) -#error "STM32_FDCAN_RF1_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_RB_NBR) -#error "STM32_FDCAN_RB_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_TEF_NBR) -#error "STM32_FDCAN_TEF_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_TB_NBR) -#error "STM32_FDCAN_TB_NBR not defined in registry" -#endif - -#if !defined(STM32_FDCAN_TM_NBR) -#error "STM32_FDCAN_TM_NBR not defined in registry" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an CAN driver. - */ -typedef struct CANDriver CANDriver; - -/** - * @brief Type of a transmission mailbox index. - */ -typedef uint32_t canmbx_t; - -#if (CAN_ENFORCE_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a CAN notification callback. - * - * @param[in] canp pointer to the @p CANDriver object triggering the - * callback - * @param[in] flags flags associated to the mailbox callback - */ -typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags); -#endif - -/** - * @brief CAN transmission frame. - * @note Accessing the frame data as word16 or word32 is not portable - * because machine data endianness, it can be still useful for a - * quick filling. - */ -typedef struct { - /** - * @brief Frame header. - */ - union { - struct { - union { - struct { - uint32_t EID:29; /**< @brief Extended identifier. */ - } ext; - struct { - uint32_t _R1:18; /**< @brief Reserved for offset. */ - uint32_t SID:11; /**< @brief Standard identifier. */ - } std; - struct { - uint32_t _R1:29; /**< @brief Reserved for offset. */ - uint32_t RTR:1; /**< @brief Remote transmit request.*/ - uint32_t XTD:1; /**< @brief Extended identifier. */ - uint32_t ESI:1; /**< @brief Error state indicator. */ - } common; - }; - uint32_t _R2:16; - uint32_t DLC:4; /**< @brief Data length code. */ - uint32_t BPS:1; /**< @brief Accepted non-matching - frame. */ - uint32_t FDF:1; /**< @brief FDCAN frame format. */ - uint32_t _R3:1; - uint32_t EFC:1; /**< @brief Event FIFO control. */ - uint32_t MM:8; /**< @brief Message event marker. */ - }; - uint32_t header32[2]; - }; - /** - * @brief Frame data. - */ - union { - uint8_t data8[CAN_MAX_DLC_BYTES]; - uint16_t data16[CAN_MAX_DLC_BYTES / 2]; - uint32_t data32[CAN_MAX_DLC_BYTES / 4]; - }; -} CANTxFrame; - -/** - * @brief CAN received frame. - * @note Accessing the frame data as word16 or word32 is not portable - * because machine data endianness, it can be still useful for a - * quick filling. - */ -typedef struct { - /** - * @brief Frame header. - */ - union { - struct { - union { - struct { - uint32_t EID:29; /**< @brief Extended identifier. */ - } ext; - struct { - uint32_t _R1:18; - uint32_t SID:11; /**< @brief Standard identifier. */ - } std; - struct { - uint32_t _R1:29; /**< @brief Reserved for offset. */ - uint32_t RTR:1; /**< @brief Remote transmit request.*/ - uint32_t XTD:1; /**< @brief Extended identifier. */ - uint32_t ESI:1; /**< @brief Error state indicator. */ - } common; - }; - uint32_t RXTS:16; /**< @brief TX time stamp. */ - uint32_t DLC:4; /**< @brief Data length code. */ - uint32_t BRS:1; /**< @brief Bit rate switch. */ - uint32_t FDF:1; /**< @brief FDCAN frame format. */ - uint32_t _R2:2; - uint32_t FIDX:7; /**< @brief Filter index. */ - uint32_t ANMF:1; /**< @brief Accepted non-matching - frame. */ - }; - uint32_t header32[2]; - }; - /** - * @brief Frame data. - */ - union { - uint8_t data8[CAN_MAX_DLC_BYTES]; - uint16_t data16[CAN_MAX_DLC_BYTES / 2]; - uint32_t data32[CAN_MAX_DLC_BYTES / 4]; - }; -} CANRxFrame; - -/** - * @brief CAN standard filter. - * @note Accessing the frame data as word16 or word32 is not portable - * because machine data endianness, it can be still useful for a - * quick filling. - */ -typedef struct { - union { - struct { - uint16_t SFID2:11; - uint8_t _R1:5; - uint16_t SFID1:11; - uint8_t SFEC:3; - uint8_t SFT:2; - }; - union { - uint32_t data32; - uint16_t data16[2]; - uint8_t data8[4]; - }; - }; -} CANRxStandardFilter; - - -/** - * @brief CAN extended filter. - * @note Accessing the frame data as word16 or word32 is not portable - * because machine data endianness, it can be still useful for a - * quick filling. -*/ -typedef struct { - union { - struct { - uint32_t EFID1:29; - uint8_t EFEC:3; - uint32_t EFID2:29; - uint8_t _R1:1; - uint8_t EFT:2; - }; - union { - uint32_t data32[2]; - uint16_t data16[4]; - uint8_t data8[8]; - }; - }; -} CANRxExtendedFilter; - - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief Nominal bit timing and prescaler register. - */ - uint32_t NBTP; - /** - * @brief Data bit timing and prescaler register. - */ - uint32_t DBTP; - /** - * @brief CC control register. - */ - uint32_t CCCR; - /** - * @brief Test configuration register. - */ - uint32_t TEST; - /** - * @brief Global filter configuration register. - */ - uint32_t RXGFC; -} CANConfig; - -/** - * @brief Structure representing an CAN driver. - */ -struct CANDriver { - /** - * @brief Driver state. - */ - canstate_t state; - /** - * @brief Current configuration data. - */ - const CANConfig *config; - /** - * @brief Transmission threads queue. - */ - threads_queue_t txqueue; - /** - * @brief Receive threads queue. - */ - threads_queue_t rxqueue; -#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__) - /** - * @brief One or more frames become available. - * @note After broadcasting this event it will not be broadcasted again - * until the received frames queue has been completely emptied. It - * is not broadcasted for each received frame. It is - * responsibility of the application to empty the queue by - * repeatedly invoking @p canReceive() when listening to this event. - * This behavior minimizes the interrupt served by the system - * because CAN traffic. - * @note The flags associated to the listeners will indicate which - * receive mailboxes become non-empty. - */ - event_source_t rxfull_event; - /** - * @brief One or more transmission mailbox become available. - * @note The flags associated to the listeners will indicate which - * transmit mailboxes become empty. - * @note The upper 16 bits are transmission error flags associated - * to the transmit mailboxes. - */ - event_source_t txempty_event; - /** - * @brief A CAN bus error happened. - * @note The flags associated to the listeners will indicate that - * receive error(s) have occurred. - * @note In this implementation the upper 16 bits are filled with the - * unprocessed content of the ESR register. - */ - event_source_t error_event; -#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) - /** - * @brief Entering sleep state event. - */ - event_source_t sleep_event; - /** - * @brief Exiting sleep state event. - */ - event_source_t wakeup_event; -#endif /* CAN_USE_SLEEP_MODE */ -#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */ - /** - * @brief One or more frames become available. - * @note After calling this function it will not be called again - * until the received frames queue has been completely emptied. It - * is not called for each received frame. It is - * responsibility of the application to empty the queue by - * repeatedly invoking @p chTryReceiveI(). - * This behavior minimizes the interrupt served by the system - * because CAN traffic. - */ - can_callback_t rxfull_cb; - /** - * @brief One or more transmission mailbox become available. - * @note The flags associated to the callback will indicate which - * transmit mailboxes become empty. - */ - can_callback_t txempty_cb; - /** - * @brief A CAN bus error happened. - */ - can_callback_t error_cb; -#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__) - /** - * @brief Exiting sleep state. - */ - can_callback_t wakeup_cb; -#endif -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the CAN registers. - */ - FDCAN_GlobalTypeDef *fdcan; - /** - * @brief Pointer to FDCAN RAM base. - */ - uint32_t *ram_base; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_CAN_USE_FDCAN1 && !defined(__DOXYGEN__) -extern CANDriver CAND1; -#endif - -#if STM32_CAN_USE_FDCAN2 && !defined(__DOXYGEN__) -extern CANDriver CAND2; -#endif - -#if STM32_CAN_USE_FDCAN3 && !defined(__DOXYGEN__) -extern CANDriver CAND3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void can_lld_init(void); - bool can_lld_start(CANDriver *canp); - void can_lld_stop(CANDriver *canp); - bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox); - void can_lld_transmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *crfp); - bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox); - void can_lld_receive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *ctfp); - void can_lld_abort(CANDriver *canp, - canmbx_t mailbox); -#if CAN_USE_SLEEP_MODE - void can_lld_sleep(CANDriver *canp); - void can_lld_wakeup(CANDriver *canp); -#endif /* CAN_USE_SLEEP_MODE */ - void can_lld_serve_interrupt(CANDriver *canp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_CAN */ - -#endif /* HAL_CAN_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file FDCANv1/hal_can_lld.h + * @brief STM32 CAN subsystem low level driver header. + * + * @addtogroup CAN + * @{ + */ + +#ifndef HAL_CAN_LLD_H +#define HAL_CAN_LLD_H + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum number of bytes in data of CAN packets. + */ +#define CAN_MAX_DLC_BYTES 64 + +/** + * @brief Number of transmit mailboxes. + */ +#define CAN_TX_MAILBOXES 1 + +/** + * @brief Number of receive mailboxes. + */ +#define CAN_RX_MAILBOXES 2 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief CAN1 driver enable switch. + * @details If set to @p TRUE the support for FDCAN1 is included. + */ +#if !defined(STM32_CAN_USE_FDCAN1) || defined(__DOXYGEN__) +#define STM32_CAN_USE_FDCAN1 FALSE +#endif + +/** + * @brief CAN2 driver enable switch. + * @details If set to @p TRUE the support for FDCAN2 is included. + */ +#if !defined(STM32_CAN_USE_FDCAN2) || defined(__DOXYGEN__) +#define STM32_CAN_USE_FDCAN2 FALSE +#endif + +/** + * @brief CAN3 driver enable switch. + * @details If set to @p TRUE the support for FDCAN3 is included. + */ +#if !defined(STM32_CAN_USE_FDCAN3) || defined(__DOXYGEN__) +#define STM32_CAN_USE_FDCAN3 FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_FDCAN1) +#error "STM32_HAS_FDCAN1 not defined in registry" +#endif + +#if !defined(STM32_HAS_FDCAN2) +#error "STM32_HAS_FDCAN2 not defined in registry" +#endif + +#if !defined(STM32_HAS_FDCAN3) +#error "STM32_HAS_FDCAN3 not defined in registry" +#endif + +#if STM32_CAN_USE_FDCAN1 && !STM32_HAS_FDCAN1 +#error "FDCAN1 not present in the selected device" +#endif + +#if STM32_CAN_USE_FDCAN2 && !STM32_HAS_FDCAN2 +#error "FDCAN2 not present in the selected device" +#endif + +#if STM32_CAN_USE_FDCAN3 && !STM32_HAS_FDCAN3 +#error "FDCAN3 not present in the selected device" +#endif + +#if !STM32_CAN_USE_FDCAN1 && !STM32_CAN_USE_FDCAN2 && !STM32_CAN_USE_FDCAN3 +#error "CAN driver activated but no FDCAN peripheral assigned" +#endif + +#if !defined(STM32_FDCAN_FLS_NBR) +#error "STM32_FDCAN_FLS_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_FLE_NBR) +#error "STM32_FDCAN_FLE_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_RF0_NBR) +#error "STM32_FDCAN_RF0_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_RF1_NBR) +#error "STM32_FDCAN_RF1_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_RB_NBR) +#error "STM32_FDCAN_RB_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_TEF_NBR) +#error "STM32_FDCAN_TEF_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_TB_NBR) +#error "STM32_FDCAN_TB_NBR not defined in registry" +#endif + +#if !defined(STM32_FDCAN_TM_NBR) +#error "STM32_FDCAN_TM_NBR not defined in registry" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an CAN driver. + */ +typedef struct CANDriver CANDriver; + +/** + * @brief Type of a transmission mailbox index. + */ +typedef uint32_t canmbx_t; + +#if (CAN_ENFORCE_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a CAN notification callback. + * + * @param[in] canp pointer to the @p CANDriver object triggering the + * callback + * @param[in] flags flags associated to the mailbox callback + */ +typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags); +#endif + +/** + * @brief CAN transmission frame. + * @note Accessing the frame data as word16 or word32 is not portable + * because machine data endianness, it can be still useful for a + * quick filling. + */ +typedef struct { + /** + * @brief Frame header. + */ + union { + struct { + union { + struct { + uint32_t EID:29; /**< @brief Extended identifier. */ + } ext; + struct { + uint32_t _R1:18; /**< @brief Reserved for offset. */ + uint32_t SID:11; /**< @brief Standard identifier. */ + } std; + struct { + uint32_t _R1:29; /**< @brief Reserved for offset. */ + uint32_t RTR:1; /**< @brief Remote transmit request.*/ + uint32_t XTD:1; /**< @brief Extended identifier. */ + uint32_t ESI:1; /**< @brief Error state indicator. */ + } common; + }; + uint32_t _R2:16; + uint32_t DLC:4; /**< @brief Data length code. */ + uint32_t BPS:1; /**< @brief Accepted non-matching + frame. */ + uint32_t FDF:1; /**< @brief FDCAN frame format. */ + uint32_t _R3:1; + uint32_t EFC:1; /**< @brief Event FIFO control. */ + uint32_t MM:8; /**< @brief Message event marker. */ + }; + uint32_t header32[2]; + }; + /** + * @brief Frame data. + */ + union { + uint8_t data8[CAN_MAX_DLC_BYTES]; + uint16_t data16[CAN_MAX_DLC_BYTES / 2]; + uint32_t data32[CAN_MAX_DLC_BYTES / 4]; + }; +} CANTxFrame; + +/** + * @brief CAN received frame. + * @note Accessing the frame data as word16 or word32 is not portable + * because machine data endianness, it can be still useful for a + * quick filling. + */ +typedef struct { + /** + * @brief Frame header. + */ + union { + struct { + union { + struct { + uint32_t EID:29; /**< @brief Extended identifier. */ + } ext; + struct { + uint32_t _R1:18; + uint32_t SID:11; /**< @brief Standard identifier. */ + } std; + struct { + uint32_t _R1:29; /**< @brief Reserved for offset. */ + uint32_t RTR:1; /**< @brief Remote transmit request.*/ + uint32_t XTD:1; /**< @brief Extended identifier. */ + uint32_t ESI:1; /**< @brief Error state indicator. */ + } common; + }; + uint32_t RXTS:16; /**< @brief TX time stamp. */ + uint32_t DLC:4; /**< @brief Data length code. */ + uint32_t BRS:1; /**< @brief Bit rate switch. */ + uint32_t FDF:1; /**< @brief FDCAN frame format. */ + uint32_t _R2:2; + uint32_t FIDX:7; /**< @brief Filter index. */ + uint32_t ANMF:1; /**< @brief Accepted non-matching + frame. */ + }; + uint32_t header32[2]; + }; + /** + * @brief Frame data. + */ + union { + uint8_t data8[CAN_MAX_DLC_BYTES]; + uint16_t data16[CAN_MAX_DLC_BYTES / 2]; + uint32_t data32[CAN_MAX_DLC_BYTES / 4]; + }; +} CANRxFrame; + +/** + * @brief CAN standard filter. + * @note Accessing the frame data as word16 or word32 is not portable + * because machine data endianness, it can be still useful for a + * quick filling. + */ +typedef struct { + union { + struct { + uint16_t SFID2:11; + uint8_t _R1:5; + uint16_t SFID1:11; + uint8_t SFEC:3; + uint8_t SFT:2; + }; + union { + uint32_t data32; + uint16_t data16[2]; + uint8_t data8[4]; + }; + }; +} CANRxStandardFilter; + + +/** + * @brief CAN extended filter. + * @note Accessing the frame data as word16 or word32 is not portable + * because machine data endianness, it can be still useful for a + * quick filling. +*/ +typedef struct { + union { + struct { + uint32_t EFID1:29; + uint8_t EFEC:3; + uint32_t EFID2:29; + uint8_t _R1:1; + uint8_t EFT:2; + }; + union { + uint32_t data32[2]; + uint16_t data16[4]; + uint8_t data8[8]; + }; + }; +} CANRxExtendedFilter; + + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief Nominal bit timing and prescaler register. + */ + uint32_t NBTP; + /** + * @brief Data bit timing and prescaler register. + */ + uint32_t DBTP; + /** + * @brief CC control register. + */ + uint32_t CCCR; + /** + * @brief Test configuration register. + */ + uint32_t TEST; + /** + * @brief Global filter configuration register. + */ + uint32_t RXGFC; +} CANConfig; + +/** + * @brief Structure representing an CAN driver. + */ +struct CANDriver { + /** + * @brief Driver state. + */ + canstate_t state; + /** + * @brief Current configuration data. + */ + const CANConfig *config; + /** + * @brief Transmission threads queue. + */ + threads_queue_t txqueue; + /** + * @brief Receive threads queue. + */ + threads_queue_t rxqueue; +#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__) + /** + * @brief One or more frames become available. + * @note After broadcasting this event it will not be broadcasted again + * until the received frames queue has been completely emptied. It + * is not broadcasted for each received frame. It is + * responsibility of the application to empty the queue by + * repeatedly invoking @p canReceive() when listening to this event. + * This behavior minimizes the interrupt served by the system + * because CAN traffic. + * @note The flags associated to the listeners will indicate which + * receive mailboxes become non-empty. + */ + event_source_t rxfull_event; + /** + * @brief One or more transmission mailbox become available. + * @note The flags associated to the listeners will indicate which + * transmit mailboxes become empty. + * @note The upper 16 bits are transmission error flags associated + * to the transmit mailboxes. + */ + event_source_t txempty_event; + /** + * @brief A CAN bus error happened. + * @note The flags associated to the listeners will indicate that + * receive error(s) have occurred. + * @note In this implementation the upper 16 bits are filled with the + * unprocessed content of the ESR register. + */ + event_source_t error_event; +#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) + /** + * @brief Entering sleep state event. + */ + event_source_t sleep_event; + /** + * @brief Exiting sleep state event. + */ + event_source_t wakeup_event; +#endif /* CAN_USE_SLEEP_MODE */ +#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */ + /** + * @brief One or more frames become available. + * @note After calling this function it will not be called again + * until the received frames queue has been completely emptied. It + * is not called for each received frame. It is + * responsibility of the application to empty the queue by + * repeatedly invoking @p chTryReceiveI(). + * This behavior minimizes the interrupt served by the system + * because CAN traffic. + */ + can_callback_t rxfull_cb; + /** + * @brief One or more transmission mailbox become available. + * @note The flags associated to the callback will indicate which + * transmit mailboxes become empty. + */ + can_callback_t txempty_cb; + /** + * @brief A CAN bus error happened. + */ + can_callback_t error_cb; +#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__) + /** + * @brief Exiting sleep state. + */ + can_callback_t wakeup_cb; +#endif +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the CAN registers. + */ + FDCAN_GlobalTypeDef *fdcan; + /** + * @brief Pointer to FDCAN RAM base. + */ + uint32_t *ram_base; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_CAN_USE_FDCAN1 && !defined(__DOXYGEN__) +extern CANDriver CAND1; +#endif + +#if STM32_CAN_USE_FDCAN2 && !defined(__DOXYGEN__) +extern CANDriver CAND2; +#endif + +#if STM32_CAN_USE_FDCAN3 && !defined(__DOXYGEN__) +extern CANDriver CAND3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void can_lld_init(void); + bool can_lld_start(CANDriver *canp); + void can_lld_stop(CANDriver *canp); + bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox); + void can_lld_transmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *crfp); + bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox); + void can_lld_receive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *ctfp); + void can_lld_abort(CANDriver *canp, + canmbx_t mailbox); +#if CAN_USE_SLEEP_MODE + void can_lld_sleep(CANDriver *canp); + void can_lld_wakeup(CANDriver *canp); +#endif /* CAN_USE_SLEEP_MODE */ + void can_lld_serve_interrupt(CANDriver *canp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_CAN */ + +#endif /* HAL_CAN_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv1/driver.mk b/os/hal/ports/STM32/LLD/GPIOv1/driver.mk index 5e428a7719..3a9768ee69 100644 --- a/os/hal/ports/STM32/LLD/GPIOv1/driver.mk +++ b/os/hal/ports/STM32/LLD/GPIOv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1 diff --git a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c index 99106bce7f..caefd2f93f 100644 --- a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c +++ b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c @@ -1,300 +1,300 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv1/hal_pal_lld.c - * @brief STM32 PAL low level driver code. - * - * @addtogroup PAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_HAS_GPIOG -#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ - RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ - RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPFEN | \ - RCC_APB2ENR_IOPGEN | RCC_APB2ENR_AFIOEN) -#elif STM32_HAS_GPIOE -#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ - RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ - RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN) -#else -#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ - RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ - RCC_APB2ENR_AFIOEN) -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Event records for the 16 GPIO EXTI channels. - */ -palevent_t _pal_events[16]; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 I/O ports configuration. - * @details Ports A-D(E, F, G) clocks enabled, AFIO clock enabled. - * - * @param[in] config the STM32 ports configuration - * - * @notapi - */ -void _pal_lld_init(const PALConfig *config) { - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) - unsigned i; - - for (i = 0; i < 16; i++) { - _pal_init_event(i); - } -#endif - - /* - * Enables the GPIO related clocks. - */ - rccEnableAPB2(APB2_EN_MASK, true); - - /* - * Initial GPIO setup. - */ - GPIOA->ODR = config->PAData.odr; - GPIOA->CRH = config->PAData.crh; - GPIOA->CRL = config->PAData.crl; - GPIOB->ODR = config->PBData.odr; - GPIOB->CRH = config->PBData.crh; - GPIOB->CRL = config->PBData.crl; - GPIOC->ODR = config->PCData.odr; - GPIOC->CRH = config->PCData.crh; - GPIOC->CRL = config->PCData.crl; - GPIOD->ODR = config->PDData.odr; - GPIOD->CRH = config->PDData.crh; - GPIOD->CRL = config->PDData.crl; -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) - GPIOE->ODR = config->PEData.odr; - GPIOE->CRH = config->PEData.crh; - GPIOE->CRL = config->PEData.crl; -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) - GPIOF->ODR = config->PFData.odr; - GPIOF->CRH = config->PFData.crh; - GPIOF->CRL = config->PFData.crl; -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) - GPIOG->ODR = config->PGData.odr; - GPIOG->CRH = config->PGData.crh; - GPIOG->CRL = config->PGData.crl; -#endif -#endif -#endif -} - -/** - * @brief Pads mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output at 2MHz. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port the port identifier - * @param[in] mask the group mask - * @param[in] mode the mode - * - * @notapi - */ -void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode) { - static const uint8_t cfgtab[] = { - 4, /* PAL_MODE_RESET, implemented as input.*/ - 2, /* PAL_MODE_UNCONNECTED, implemented as push pull output 2MHz.*/ - 4, /* PAL_MODE_INPUT */ - 8, /* PAL_MODE_INPUT_PULLUP */ - 8, /* PAL_MODE_INPUT_PULLDOWN */ - 0, /* PAL_MODE_INPUT_ANALOG */ - 3, /* PAL_MODE_OUTPUT_PUSHPULL, 50MHz.*/ - 7, /* PAL_MODE_OUTPUT_OPENDRAIN, 50MHz.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 0xB, /* PAL_MODE_STM32_ALTERNATE_PUSHPULL, 50MHz.*/ - 0xF, /* PAL_MODE_STM32_ALTERNATE_OPENDRAIN, 50MHz.*/ - }; - uint32_t mh, ml, crh, crl, cfg; - unsigned i; - - if (mode == PAL_MODE_INPUT_PULLUP) - port->BSRR = mask; - else if (mode == PAL_MODE_INPUT_PULLDOWN) - port->BRR = mask; - cfg = cfgtab[mode]; - mh = ml = crh = crl = 0; - for (i = 0; i < 8; i++) { - ml <<= 4; - mh <<= 4; - crl <<= 4; - crh <<= 4; - if ((mask & 0x0080) == 0) - ml |= 0xf; - else - crl |= cfg; - if ((mask & 0x8000) == 0) - mh |= 0xf; - else - crh |= cfg; - mask <<= 1; - } - port->CRH = (port->CRH & mh) | crh; - port->CRL = (port->CRL & ml) | crl; -} - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) -/** - * @brief Pad event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad event mode - * - * @notapi - */ -void _pal_lld_enablepadevent(ioportid_t port, - iopadid_t pad, - ioeventmode_t mode) { - - uint32_t padmask, cridx, croff, crmask, portidx; - - /* Mask of the pad.*/ - padmask = 1U << (uint32_t)pad; - - /* Multiple channel setting of the same channel not allowed, first disable - it. This is done because on STM32 the same channel cannot be mapped on - multiple ports.*/ - osalDbgAssert(((EXTI->RTSR & padmask) == 0U) && - ((EXTI->FTSR & padmask) == 0U), "channel already in use"); - - /* Index and mask of the SYSCFG CR register to be used.*/ - cridx = (uint32_t)pad >> 2U; - croff = ((uint32_t)pad & 3U) * 4U; - crmask = ~(0xFU << croff); - - /* Port index is obtained assuming that GPIO ports are placed at regular - 0x400 intervals in memory space. So far this is true for all devices.*/ - portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; - - /* Port selection in SYSCFG.*/ - AFIO->EXTICR[cridx] = (AFIO->EXTICR[cridx] & crmask) | (portidx << croff); - - /* Programming edge registers.*/ - if (mode & PAL_EVENT_MODE_RISING_EDGE) - EXTI->RTSR |= padmask; - else - EXTI->RTSR &= ~padmask; - if (mode & PAL_EVENT_MODE_FALLING_EDGE) - EXTI->FTSR |= padmask; - else - EXTI->FTSR &= ~padmask; - - /* Programming interrupt and event registers.*/ - EXTI->IMR |= padmask; - EXTI->EMR &= ~padmask; -} - -/** - * @brief Pad event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) { - uint32_t padmask, rtsr1, ftsr1; - - rtsr1 = EXTI->RTSR; - ftsr1 = EXTI->FTSR; - - /* Mask of the pad.*/ - padmask = 1U << (uint32_t)pad; - - /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/ - if (((rtsr1 | ftsr1) & padmask) != 0U) { - uint32_t cridx, croff, crport, portidx; - - /* Index and mask of the SYSCFG CR register to be used.*/ - cridx = (uint32_t)pad >> 2U; - croff = ((uint32_t)pad & 3U) * 4U; - - /* Port index is obtained assuming that GPIO ports are placed at regular - 0x400 intervals in memory space. So far this is true for all devices.*/ - portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; - - crport = (AFIO->EXTICR[cridx] >> croff) & 0xFU; - - osalDbgAssert(crport == portidx, "channel mapped on different port"); - - /* Disabling channel.*/ - EXTI->IMR &= ~padmask; - EXTI->EMR &= ~padmask; - EXTI->RTSR = rtsr1 & ~padmask; - EXTI->FTSR = ftsr1 & ~padmask; - EXTI->PR = padmask; - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT - /* Callback cleared and/or thread reset.*/ - _pal_clear_event(pad); -#endif - } -} -#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */ - -#endif /* HAL_USE_PAL */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv1/hal_pal_lld.c + * @brief STM32 PAL low level driver code. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_HAS_GPIOG +#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ + RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ + RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPFEN | \ + RCC_APB2ENR_IOPGEN | RCC_APB2ENR_AFIOEN) +#elif STM32_HAS_GPIOE +#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ + RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ + RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN) +#else +#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ + RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ + RCC_APB2ENR_AFIOEN) +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Event records for the 16 GPIO EXTI channels. + */ +palevent_t _pal_events[16]; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 I/O ports configuration. + * @details Ports A-D(E, F, G) clocks enabled, AFIO clock enabled. + * + * @param[in] config the STM32 ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) { + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) + unsigned i; + + for (i = 0; i < 16; i++) { + _pal_init_event(i); + } +#endif + + /* + * Enables the GPIO related clocks. + */ + rccEnableAPB2(APB2_EN_MASK, true); + + /* + * Initial GPIO setup. + */ + GPIOA->ODR = config->PAData.odr; + GPIOA->CRH = config->PAData.crh; + GPIOA->CRL = config->PAData.crl; + GPIOB->ODR = config->PBData.odr; + GPIOB->CRH = config->PBData.crh; + GPIOB->CRL = config->PBData.crl; + GPIOC->ODR = config->PCData.odr; + GPIOC->CRH = config->PCData.crh; + GPIOC->CRL = config->PCData.crl; + GPIOD->ODR = config->PDData.odr; + GPIOD->CRH = config->PDData.crh; + GPIOD->CRL = config->PDData.crl; +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + GPIOE->ODR = config->PEData.odr; + GPIOE->CRH = config->PEData.crh; + GPIOE->CRL = config->PEData.crl; +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + GPIOF->ODR = config->PFData.odr; + GPIOF->CRH = config->PFData.crh; + GPIOF->CRL = config->PFData.crl; +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + GPIOG->ODR = config->PGData.odr; + GPIOG->CRH = config->PGData.crh; + GPIOG->CRL = config->PGData.crl; +#endif +#endif +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output at 2MHz. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + static const uint8_t cfgtab[] = { + 4, /* PAL_MODE_RESET, implemented as input.*/ + 2, /* PAL_MODE_UNCONNECTED, implemented as push pull output 2MHz.*/ + 4, /* PAL_MODE_INPUT */ + 8, /* PAL_MODE_INPUT_PULLUP */ + 8, /* PAL_MODE_INPUT_PULLDOWN */ + 0, /* PAL_MODE_INPUT_ANALOG */ + 3, /* PAL_MODE_OUTPUT_PUSHPULL, 50MHz.*/ + 7, /* PAL_MODE_OUTPUT_OPENDRAIN, 50MHz.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 0xB, /* PAL_MODE_STM32_ALTERNATE_PUSHPULL, 50MHz.*/ + 0xF, /* PAL_MODE_STM32_ALTERNATE_OPENDRAIN, 50MHz.*/ + }; + uint32_t mh, ml, crh, crl, cfg; + unsigned i; + + if (mode == PAL_MODE_INPUT_PULLUP) + port->BSRR = mask; + else if (mode == PAL_MODE_INPUT_PULLDOWN) + port->BRR = mask; + cfg = cfgtab[mode]; + mh = ml = crh = crl = 0; + for (i = 0; i < 8; i++) { + ml <<= 4; + mh <<= 4; + crl <<= 4; + crh <<= 4; + if ((mask & 0x0080) == 0) + ml |= 0xf; + else + crl |= cfg; + if ((mask & 0x8000) == 0) + mh |= 0xf; + else + crh |= cfg; + mask <<= 1; + } + port->CRH = (port->CRH & mh) | crh; + port->CRL = (port->CRL & ml) | crl; +} + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Pad event enable. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad event mode + * + * @notapi + */ +void _pal_lld_enablepadevent(ioportid_t port, + iopadid_t pad, + ioeventmode_t mode) { + + uint32_t padmask, cridx, croff, crmask, portidx; + + /* Mask of the pad.*/ + padmask = 1U << (uint32_t)pad; + + /* Multiple channel setting of the same channel not allowed, first disable + it. This is done because on STM32 the same channel cannot be mapped on + multiple ports.*/ + osalDbgAssert(((EXTI->RTSR & padmask) == 0U) && + ((EXTI->FTSR & padmask) == 0U), "channel already in use"); + + /* Index and mask of the SYSCFG CR register to be used.*/ + cridx = (uint32_t)pad >> 2U; + croff = ((uint32_t)pad & 3U) * 4U; + crmask = ~(0xFU << croff); + + /* Port index is obtained assuming that GPIO ports are placed at regular + 0x400 intervals in memory space. So far this is true for all devices.*/ + portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; + + /* Port selection in SYSCFG.*/ + AFIO->EXTICR[cridx] = (AFIO->EXTICR[cridx] & crmask) | (portidx << croff); + + /* Programming edge registers.*/ + if (mode & PAL_EVENT_MODE_RISING_EDGE) + EXTI->RTSR |= padmask; + else + EXTI->RTSR &= ~padmask; + if (mode & PAL_EVENT_MODE_FALLING_EDGE) + EXTI->FTSR |= padmask; + else + EXTI->FTSR &= ~padmask; + + /* Programming interrupt and event registers.*/ + EXTI->IMR |= padmask; + EXTI->EMR &= ~padmask; +} + +/** + * @brief Pad event disable. + * @details This function disables previously programmed event callbacks. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) { + uint32_t padmask, rtsr1, ftsr1; + + rtsr1 = EXTI->RTSR; + ftsr1 = EXTI->FTSR; + + /* Mask of the pad.*/ + padmask = 1U << (uint32_t)pad; + + /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/ + if (((rtsr1 | ftsr1) & padmask) != 0U) { + uint32_t cridx, croff, crport, portidx; + + /* Index and mask of the SYSCFG CR register to be used.*/ + cridx = (uint32_t)pad >> 2U; + croff = ((uint32_t)pad & 3U) * 4U; + + /* Port index is obtained assuming that GPIO ports are placed at regular + 0x400 intervals in memory space. So far this is true for all devices.*/ + portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; + + crport = (AFIO->EXTICR[cridx] >> croff) & 0xFU; + + osalDbgAssert(crport == portidx, "channel mapped on different port"); + + /* Disabling channel.*/ + EXTI->IMR &= ~padmask; + EXTI->EMR &= ~padmask; + EXTI->RTSR = rtsr1 & ~padmask; + EXTI->FTSR = ftsr1 & ~padmask; + EXTI->PR = padmask; + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT + /* Callback cleared and/or thread reset.*/ + _pal_clear_event(pad); +#endif + } +} +#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */ + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h index 63bc006d44..2b7d2dfc0d 100644 --- a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h +++ b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h @@ -1,459 +1,459 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv1/hal_pal_lld.h - * @brief STM32 PAL low level driver header. - * - * @addtogroup PAL - * @{ - */ - -#ifndef HAL_PAL_LLD_H -#define HAL_PAL_LLD_H - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Unsupported modes and specific modes */ -/*===========================================================================*/ - -/** - * @name STM32-specific I/O mode flags - * @{ - */ -/** - * @brief STM32 specific alternate push-pull output mode. - */ -#define PAL_MODE_STM32_ALTERNATE_PUSHPULL 16 - -/** - * @brief STM32 specific alternate open-drain output mode. - */ -#define PAL_MODE_STM32_ALTERNATE_OPENDRAIN 17 -/** @} */ - -/*===========================================================================*/ -/* I/O Ports Types and constants. */ -/*===========================================================================*/ - -/** - * @name Port related definitions - * @{ - */ -/** - * @brief Width, in bits, of an I/O port. - */ -#define PAL_IOPORTS_WIDTH 16 - -/** - * @brief Whole port mask. - * @details This macro specifies all the valid bits into a port. - */ -#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) -/** @} */ - -/** - * @name Line handling macros - * @{ - */ -/** - * @brief Forms a line identifier. - * @details A port/pad pair are encoded into an @p ioline_t type. The encoding - * of this type is platform-dependent. - * @note In this driver the pad number is encoded in the lower 4 bits of - * the GPIO address which are guaranteed to be zero. - */ -#define PAL_LINE(port, pad) \ - ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) - -/** - * @brief Decodes a port identifier from a line identifier. - */ -#define PAL_PORT(line) \ - ((GPIO_TypeDef *)(((uint32_t)(line)) & 0xFFFFFFF0U)) - -/** - * @brief Decodes a pad identifier from a line identifier. - */ -#define PAL_PAD(line) \ - ((uint32_t)((uint32_t)(line) & 0x0000000FU)) - -/** - * @brief Value identifying an invalid line. - */ -#define PAL_NOLINE 0U -/** @} */ - -/** - * @brief GPIO port setup info. - */ -typedef struct { - /** Initial value for ODR register.*/ - uint32_t odr; - /** Initial value for CRL register.*/ - uint32_t crl; - /** Initial value for CRH register.*/ - uint32_t crh; -} stm32_gpio_setup_t; - -/** - * @brief STM32 GPIO static initializer. - * @details An instance of this structure must be passed to @p palInit() at - * system startup time in order to initialize the digital I/O - * subsystem. This represents only the initial setup, specific pads - * or whole ports can be reprogrammed at later time. - */ -typedef struct { - /** @brief Port A setup data.*/ - stm32_gpio_setup_t PAData; - /** @brief Port B setup data.*/ - stm32_gpio_setup_t PBData; - /** @brief Port C setup data.*/ - stm32_gpio_setup_t PCData; - /** @brief Port D setup data.*/ - stm32_gpio_setup_t PDData; -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) - /** @brief Port E setup data.*/ - stm32_gpio_setup_t PEData; -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) - /** @brief Port F setup data.*/ - stm32_gpio_setup_t PFData; -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) - /** @brief Port G setup data.*/ - stm32_gpio_setup_t PGData; -#endif -#endif -#endif -} PALConfig; - -/** - * @brief Digital I/O port sized unsigned type. - */ -typedef uint32_t ioportmask_t; - -/** - * @brief Digital I/O modes. - */ -typedef uint32_t iomode_t; - -/** - * @brief Type of an I/O line. - */ -typedef uint32_t ioline_t; - -/** - * @brief Type of an event mode. - */ -typedef uint32_t ioeventmode_t; - -/** - * @brief Port Identifier. - * @details This type can be a scalar or some kind of pointer, do not make - * any assumption about it, use the provided macros when populating - * variables of this type. - */ -typedef GPIO_TypeDef * ioportid_t; - -/** - * @brief Type of an pad identifier. - */ -typedef uint32_t iopadid_t; - -/*===========================================================================*/ -/* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ -/*===========================================================================*/ - -/** - * @brief GPIO port A identifier. - */ -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) -#define IOPORT1 GPIOA -#endif - -/** - * @brief GPIO port B identifier. - */ -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) -#define IOPORT2 GPIOB -#endif - -/** - * @brief GPIO port C identifier. - */ -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) -#define IOPORT3 GPIOC -#endif - -/** - * @brief GPIO port D identifier. - */ -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) -#define IOPORT4 GPIOD -#endif - -/** - * @brief GPIO port E identifier. - */ -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) -#define IOPORT5 GPIOE -#endif - -/** - * @brief GPIO port F identifier. - */ -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) -#define IOPORT6 GPIOF -#endif - -/** - * @brief GPIO port G identifier. - */ -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) -#define IOPORT7 GPIOG -#endif - -/*===========================================================================*/ -/* Implementation, some of the following macros could be implemented as */ -/* functions, if so please put them in pal_lld.c. */ -/*===========================================================================*/ - -/** - * @brief GPIO ports subsystem initialization. - * - * @notapi - */ -#define pal_lld_init(config) _pal_lld_init(config) - -/** - * @brief Reads an I/O port. - * @details This function is implemented by reading the GPIO IDR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The port bits. - * - * @notapi - */ -#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR)) - -/** - * @brief Reads the output latch. - * @details This function is implemented by reading the GPIO ODR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The latched logical states. - * - * @notapi - */ -#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR)) - -/** - * @brief Writes on a I/O port. - * @details This function is implemented by writing the GPIO ODR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] bits bits to be written on the specified port - * - * @notapi - */ -#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits)) - -/** - * @brief Sets a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] bits bits to be ORed on the specified port - * - * @notapi - */ -#define pal_lld_setport(port, bits) ((port)->BSRR = (uint32_t)(bits)) - -/** - * @brief Clears a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BRR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] bits bits to be cleared on the specified port - * - * @notapi - */ -#define pal_lld_clearport(port, bits) ((port)->BRR = (uint32_t)(bits)) - -/** - * @brief Writes a group of bits. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset the group bit offset within the port - * @param[in] bits bits to be written. Values exceeding the group - * width are masked. - * - * @notapi - */ -#define pal_lld_writegroup(port, mask, offset, bits) { \ - uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \ - ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \ - (port)->BSRR = w; \ -} - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset group bit offset within the port - * @param[in] mode group mode - * - * @notapi - */ -#define pal_lld_setgroupmode(port, mask, offset, mode) \ - _pal_lld_setgroupmode(port, mask << offset, mode) - -/** - * @brief Writes a logical state on an output pad. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] bit logical value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @notapi - */ -#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) - -/** - * @brief Pad event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad event mode - * - * @notapi - */ -#define pal_lld_enablepadevent(port, pad, mode) \ - _pal_lld_enablepadevent(port, pad, mode) - -/** - * @brief Pad event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -#define pal_lld_disablepadevent(port, pad) \ - _pal_lld_disablepadevent(port, pad) - -/** - * @brief Returns a PAL event structure associated to a pad. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -#define pal_lld_get_pad_event(port, pad) \ - &_pal_events[pad]; (void)(port) - -/** - * @brief Returns a PAL event structure associated to a line. - * - * @param[in] line line identifier - * - * @notapi - */ -#define pal_lld_get_line_event(line) \ - &_pal_events[PAL_PAD(line)] - -/** - * @brief Pad event enable check. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @return Pad event status. - * @retval false if the pad event is disabled. - * @retval true if the pad event is enabled. - * - * @notapi - */ -#define pal_lld_ispadeventenabled(port, pad) \ - (bool)((EXTI->IMR & (1U << (uint32_t)pad)) != 0U) - -#if !defined(__DOXYGEN__) -extern const PALConfig pal_default_config; -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) -extern palevent_t _pal_events[16]; -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void _pal_lld_init(const PALConfig *config); - void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode); -#if PAL_USE_CALLBACKS || PAL_USE_WAIT - void _pal_lld_enablepadevent(ioportid_t port, - iopadid_t pad, - ioeventmode_t mode); - void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PAL */ - -#endif /* HAL_PAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv1/hal_pal_lld.h + * @brief STM32 PAL low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef HAL_PAL_LLD_H +#define HAL_PAL_LLD_H + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +/** + * @name STM32-specific I/O mode flags + * @{ + */ +/** + * @brief STM32 specific alternate push-pull output mode. + */ +#define PAL_MODE_STM32_ALTERNATE_PUSHPULL 16 + +/** + * @brief STM32 specific alternate open-drain output mode. + */ +#define PAL_MODE_STM32_ALTERNATE_OPENDRAIN 17 +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @name Port related definitions + * @{ + */ +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16 + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) +/** @} */ + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver the pad number is encoded in the lower 4 bits of + * the GPIO address which are guaranteed to be zero. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) + +/** + * @brief Decodes a port identifier from a line identifier. + */ +#define PAL_PORT(line) \ + ((GPIO_TypeDef *)(((uint32_t)(line)) & 0xFFFFFFF0U)) + +/** + * @brief Decodes a pad identifier from a line identifier. + */ +#define PAL_PAD(line) \ + ((uint32_t)((uint32_t)(line) & 0x0000000FU)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0U +/** @} */ + +/** + * @brief GPIO port setup info. + */ +typedef struct { + /** Initial value for ODR register.*/ + uint32_t odr; + /** Initial value for CRL register.*/ + uint32_t crl; + /** Initial value for CRH register.*/ + uint32_t crh; +} stm32_gpio_setup_t; + +/** + * @brief STM32 GPIO static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialize the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct { + /** @brief Port A setup data.*/ + stm32_gpio_setup_t PAData; + /** @brief Port B setup data.*/ + stm32_gpio_setup_t PBData; + /** @brief Port C setup data.*/ + stm32_gpio_setup_t PCData; + /** @brief Port D setup data.*/ + stm32_gpio_setup_t PDData; +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + /** @brief Port E setup data.*/ + stm32_gpio_setup_t PEData; +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + /** @brief Port F setup data.*/ + stm32_gpio_setup_t PFData; +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + /** @brief Port G setup data.*/ + stm32_gpio_setup_t PGData; +#endif +#endif +#endif +} PALConfig; + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Type of an I/O line. + */ +typedef uint32_t ioline_t; + +/** + * @brief Type of an event mode. + */ +typedef uint32_t ioeventmode_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef GPIO_TypeDef * ioportid_t; + +/** + * @brief Type of an pad identifier. + */ +typedef uint32_t iopadid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/* The low level driver wraps the definitions already present in the STM32 */ +/* firmware library. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) +#define IOPORT1 GPIOA +#endif + +/** + * @brief GPIO port B identifier. + */ +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) +#define IOPORT2 GPIOB +#endif + +/** + * @brief GPIO port C identifier. + */ +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) +#define IOPORT3 GPIOC +#endif + +/** + * @brief GPIO port D identifier. + */ +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) +#define IOPORT4 GPIOD +#endif + +/** + * @brief GPIO port E identifier. + */ +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) +#define IOPORT5 GPIOE +#endif + +/** + * @brief GPIO port F identifier. + */ +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) +#define IOPORT6 GPIOF +#endif + +/** + * @brief GPIO port G identifier. + */ +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) +#define IOPORT7 GPIOG +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief GPIO ports subsystem initialization. + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the GPIO IDR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR)) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the GPIO ODR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR)) + +/** + * @brief Writes on a I/O port. + * @details This function is implemented by writing the GPIO ODR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) ((port)->BSRR = (uint32_t)(bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BRR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) ((port)->BRR = (uint32_t)(bits)) + +/** + * @brief Writes a group of bits. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group + * width are masked. + * + * @notapi + */ +#define pal_lld_writegroup(port, mask, offset, bits) { \ + uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \ + ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \ + (port)->BSRR = w; \ +} + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Writes a logical state on an output pad. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) + +/** + * @brief Pad event enable. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad event mode + * + * @notapi + */ +#define pal_lld_enablepadevent(port, pad, mode) \ + _pal_lld_enablepadevent(port, pad, mode) + +/** + * @brief Pad event disable. + * @details This function disables previously programmed event callbacks. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_disablepadevent(port, pad) \ + _pal_lld_disablepadevent(port, pad) + +/** + * @brief Returns a PAL event structure associated to a pad. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_get_pad_event(port, pad) \ + &_pal_events[pad]; (void)(port) + +/** + * @brief Returns a PAL event structure associated to a line. + * + * @param[in] line line identifier + * + * @notapi + */ +#define pal_lld_get_line_event(line) \ + &_pal_events[PAL_PAD(line)] + +/** + * @brief Pad event enable check. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return Pad event status. + * @retval false if the pad event is disabled. + * @retval true if the pad event is enabled. + * + * @notapi + */ +#define pal_lld_ispadeventenabled(port, pad) \ + (bool)((EXTI->IMR & (1U << (uint32_t)pad)) != 0U) + +#if !defined(__DOXYGEN__) +extern const PALConfig pal_default_config; +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) +extern palevent_t _pal_events[16]; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); +#if PAL_USE_CALLBACKS || PAL_USE_WAIT + void _pal_lld_enablepadevent(ioportid_t port, + iopadid_t pad, + ioeventmode_t mode); + void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* HAL_PAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv2/driver.mk b/os/hal/ports/STM32/LLD/GPIOv2/driver.mk index 387ed83f5a..304546bba6 100644 --- a/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +++ b/os/hal/ports/STM32/LLD/GPIOv2/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2 diff --git a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c index ef2fb9a16d..1973e67c61 100644 --- a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c +++ b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c @@ -1,271 +1,271 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv2/hal_pal_lld.c - * @brief STM32 PAL low level driver code. - * - * @addtogroup PAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Event records for the 16 GPIO EXTI channels. - */ -palevent_t _pal_events[16]; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief PAL driver initialization. - * - * @notapi - */ -void _pal_lld_init(void) { - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) - unsigned i; - - for (i = 0; i < 16; i++) { - _pal_init_event(i); - } -#endif -} - -/** - * @brief Pads mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum - * speed. - * - * @param[in] port the port identifier - * @param[in] mask the group mask - * @param[in] mode the mode - * - * @notapi - */ -void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode) { - - uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0; - uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2; - uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3; - uint32_t pupdr = (mode & PAL_STM32_PUPDR_MASK) >> 5; - uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7; - uint32_t bit = 0; - while (true) { - if ((mask & 1) != 0) { - uint32_t altrmask, m1, m2, m4; - - altrmask = altr << ((bit & 7) * 4); - m1 = 1 << bit; - m2 = 3 << (bit * 2); - m4 = 15 << ((bit & 7) * 4); - port->OTYPER = (port->OTYPER & ~m1) | otyper; - port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr; - port->PUPDR = (port->PUPDR & ~m2) | pupdr; - if ((mode & PAL_STM32_MODE_MASK) == PAL_STM32_MODE_ALTERNATE) { - /* If going in alternate mode then the alternate number is set - before switching mode in order to avoid glitches.*/ - if (bit < 8) - port->AFRL = (port->AFRL & ~m4) | altrmask; - else - port->AFRH = (port->AFRH & ~m4) | altrmask; - port->MODER = (port->MODER & ~m2) | moder; - } - else { - /* If going into a non-alternate mode then the mode is switched - before setting the alternate mode in order to avoid glitches.*/ - port->MODER = (port->MODER & ~m2) | moder; - if (bit < 8) - port->AFRL = (port->AFRL & ~m4) | altrmask; - else - port->AFRH = (port->AFRH & ~m4) | altrmask; - } - } - mask >>= 1; - if (!mask) - return; - otyper <<= 1; - ospeedr <<= 2; - pupdr <<= 2; - moder <<= 2; - bit++; - } -} - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) -/** - * @brief Pad event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad event mode - * - * @notapi - */ -void _pal_lld_enablepadevent(ioportid_t port, - iopadid_t pad, - ioeventmode_t mode) { - - uint32_t padmask, cridx, croff, crmask, portidx; - - /* Mask of the pad.*/ - padmask = 1U << (uint32_t)pad; - - /* Multiple channel setting of the same channel not allowed, first disable - it. This is done because on STM32 the same channel cannot be mapped on - multiple ports.*/ - osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) && - ((EXTI->FTSR1 & padmask) == 0U), "channel already in use"); - - /* Port index is obtained assuming that GPIO ports are placed at regular - 0x400 intervals in memory space. So far this is true for all devices.*/ - portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; - - /* Index and mask of the CR register to be used.*/ - cridx = (uint32_t)pad >> 2U; -#if STM32_EXTI_HAS_CR == FALSE - croff = ((uint32_t)pad & 3U) * 4U; - crmask = ~(0xFU << croff); - SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff); -#else - croff = ((uint32_t)pad & 3U) * 8U; - crmask = ~(0xFFU << croff); - EXTI->EXTICR[cridx] = (EXTI->EXTICR[cridx] & crmask) | (portidx << croff); -#endif - - /* Programming edge registers.*/ - if (mode & PAL_EVENT_MODE_RISING_EDGE) - EXTI->RTSR1 |= padmask; - else - EXTI->RTSR1 &= ~padmask; - if (mode & PAL_EVENT_MODE_FALLING_EDGE) - EXTI->FTSR1 |= padmask; - else - EXTI->FTSR1 &= ~padmask; - - /* Programming interrupt and event registers.*/ -#if defined(STM32_EXTI_ENHANCED) - EXTI_D1->IMR1 |= padmask; - EXTI_D1->EMR1 &= ~padmask; -#else - EXTI->IMR1 |= padmask; - EXTI->EMR1 &= ~padmask; -#endif -} - -/** - * @brief Pad event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) { - uint32_t padmask, rtsr1, ftsr1; - - rtsr1 = EXTI->RTSR1; - ftsr1 = EXTI->FTSR1; - - /* Mask of the pad.*/ - padmask = 1U << (uint32_t)pad; - - /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/ - if (((rtsr1 | ftsr1) & padmask) != 0U) { - uint32_t cridx, croff, crport, portidx; - - /* Port index is obtained assuming that GPIO ports are placed at regular - 0x400 intervals in memory space. So far this is true for all devices.*/ - portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; - - /* Index and mask of the CR register to be used.*/ - cridx = (uint32_t)pad >> 2U; -#if STM32_EXTI_HAS_CR == FALSE - croff = ((uint32_t)pad & 3U) * 4U; - crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU; -#else - croff = ((uint32_t)pad & 3U) * 8U; - crport = (EXTI->EXTICR[cridx] >> croff) & 0xFFU; -#endif - - osalDbgAssert(crport == portidx, "channel mapped on different port"); - -#if defined(STM32_EXTI_ENHANCED) - /* Disabling channel.*/ - EXTI_D1->IMR1 &= ~padmask; - EXTI_D1->EMR1 &= ~padmask; - EXTI->RTSR1 = rtsr1 & ~padmask; - EXTI->FTSR1 = ftsr1 & ~padmask; - EXTI_D1->PR1 = padmask; -#else - /* Disabling channel.*/ - EXTI->IMR1 &= ~padmask; - EXTI->EMR1 &= ~padmask; - EXTI->RTSR1 = rtsr1 & ~padmask; - EXTI->FTSR1 = ftsr1 & ~padmask; -#if STM32_EXTI_SEPARATE_RF == FALSE - EXTI->PR1 = padmask; -#else - EXTI->RPR1 = padmask; - EXTI->FPR1 = padmask; -#endif -#endif - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT - /* Callback cleared and/or thread reset.*/ - _pal_clear_event(pad); -#endif - } -} -#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */ - -#endif /* HAL_USE_PAL */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv2/hal_pal_lld.c + * @brief STM32 PAL low level driver code. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Event records for the 16 GPIO EXTI channels. + */ +palevent_t _pal_events[16]; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief PAL driver initialization. + * + * @notapi + */ +void _pal_lld_init(void) { + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) + unsigned i; + + for (i = 0; i < 16; i++) { + _pal_init_event(i); + } +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum + * speed. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + + uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0; + uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2; + uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3; + uint32_t pupdr = (mode & PAL_STM32_PUPDR_MASK) >> 5; + uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7; + uint32_t bit = 0; + while (true) { + if ((mask & 1) != 0) { + uint32_t altrmask, m1, m2, m4; + + altrmask = altr << ((bit & 7) * 4); + m1 = 1 << bit; + m2 = 3 << (bit * 2); + m4 = 15 << ((bit & 7) * 4); + port->OTYPER = (port->OTYPER & ~m1) | otyper; + port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr; + port->PUPDR = (port->PUPDR & ~m2) | pupdr; + if ((mode & PAL_STM32_MODE_MASK) == PAL_STM32_MODE_ALTERNATE) { + /* If going in alternate mode then the alternate number is set + before switching mode in order to avoid glitches.*/ + if (bit < 8) + port->AFRL = (port->AFRL & ~m4) | altrmask; + else + port->AFRH = (port->AFRH & ~m4) | altrmask; + port->MODER = (port->MODER & ~m2) | moder; + } + else { + /* If going into a non-alternate mode then the mode is switched + before setting the alternate mode in order to avoid glitches.*/ + port->MODER = (port->MODER & ~m2) | moder; + if (bit < 8) + port->AFRL = (port->AFRL & ~m4) | altrmask; + else + port->AFRH = (port->AFRH & ~m4) | altrmask; + } + } + mask >>= 1; + if (!mask) + return; + otyper <<= 1; + ospeedr <<= 2; + pupdr <<= 2; + moder <<= 2; + bit++; + } +} + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Pad event enable. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad event mode + * + * @notapi + */ +void _pal_lld_enablepadevent(ioportid_t port, + iopadid_t pad, + ioeventmode_t mode) { + + uint32_t padmask, cridx, croff, crmask, portidx; + + /* Mask of the pad.*/ + padmask = 1U << (uint32_t)pad; + + /* Multiple channel setting of the same channel not allowed, first disable + it. This is done because on STM32 the same channel cannot be mapped on + multiple ports.*/ + osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) && + ((EXTI->FTSR1 & padmask) == 0U), "channel already in use"); + + /* Port index is obtained assuming that GPIO ports are placed at regular + 0x400 intervals in memory space. So far this is true for all devices.*/ + portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; + + /* Index and mask of the CR register to be used.*/ + cridx = (uint32_t)pad >> 2U; +#if STM32_EXTI_HAS_CR == FALSE + croff = ((uint32_t)pad & 3U) * 4U; + crmask = ~(0xFU << croff); + SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff); +#else + croff = ((uint32_t)pad & 3U) * 8U; + crmask = ~(0xFFU << croff); + EXTI->EXTICR[cridx] = (EXTI->EXTICR[cridx] & crmask) | (portidx << croff); +#endif + + /* Programming edge registers.*/ + if (mode & PAL_EVENT_MODE_RISING_EDGE) + EXTI->RTSR1 |= padmask; + else + EXTI->RTSR1 &= ~padmask; + if (mode & PAL_EVENT_MODE_FALLING_EDGE) + EXTI->FTSR1 |= padmask; + else + EXTI->FTSR1 &= ~padmask; + + /* Programming interrupt and event registers.*/ +#if defined(STM32_EXTI_ENHANCED) + EXTI_D1->IMR1 |= padmask; + EXTI_D1->EMR1 &= ~padmask; +#else + EXTI->IMR1 |= padmask; + EXTI->EMR1 &= ~padmask; +#endif +} + +/** + * @brief Pad event disable. + * @details This function disables previously programmed event callbacks. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) { + uint32_t padmask, rtsr1, ftsr1; + + rtsr1 = EXTI->RTSR1; + ftsr1 = EXTI->FTSR1; + + /* Mask of the pad.*/ + padmask = 1U << (uint32_t)pad; + + /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/ + if (((rtsr1 | ftsr1) & padmask) != 0U) { + uint32_t cridx, croff, crport, portidx; + + /* Port index is obtained assuming that GPIO ports are placed at regular + 0x400 intervals in memory space. So far this is true for all devices.*/ + portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; + + /* Index and mask of the CR register to be used.*/ + cridx = (uint32_t)pad >> 2U; +#if STM32_EXTI_HAS_CR == FALSE + croff = ((uint32_t)pad & 3U) * 4U; + crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU; +#else + croff = ((uint32_t)pad & 3U) * 8U; + crport = (EXTI->EXTICR[cridx] >> croff) & 0xFFU; +#endif + + osalDbgAssert(crport == portidx, "channel mapped on different port"); + +#if defined(STM32_EXTI_ENHANCED) + /* Disabling channel.*/ + EXTI_D1->IMR1 &= ~padmask; + EXTI_D1->EMR1 &= ~padmask; + EXTI->RTSR1 = rtsr1 & ~padmask; + EXTI->FTSR1 = ftsr1 & ~padmask; + EXTI_D1->PR1 = padmask; +#else + /* Disabling channel.*/ + EXTI->IMR1 &= ~padmask; + EXTI->EMR1 &= ~padmask; + EXTI->RTSR1 = rtsr1 & ~padmask; + EXTI->FTSR1 = ftsr1 & ~padmask; +#if STM32_EXTI_SEPARATE_RF == FALSE + EXTI->PR1 = padmask; +#else + EXTI->RPR1 = padmask; + EXTI->FPR1 = padmask; +#endif +#endif + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT + /* Callback cleared and/or thread reset.*/ + _pal_clear_event(pad); +#endif + } +} +#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */ + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h index 15b541b056..5a322ca6c0 100644 --- a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h +++ b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h @@ -1,514 +1,514 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv2/hal_pal_lld.h - * @brief STM32 PAL low level driver header. - * - * @addtogroup PAL - * @{ - */ - -#ifndef HAL_PAL_LLD_H -#define HAL_PAL_LLD_H - -#include "stm32_gpio.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Unsupported modes and specific modes */ -/*===========================================================================*/ - -/* Specifies palInit() without parameter, required until all platforms will - be updated to the new style.*/ -#define PAL_NEW_INIT - -#undef PAL_MODE_RESET -#undef PAL_MODE_UNCONNECTED -#undef PAL_MODE_INPUT -#undef PAL_MODE_INPUT_PULLUP -#undef PAL_MODE_INPUT_PULLDOWN -#undef PAL_MODE_INPUT_ANALOG -#undef PAL_MODE_OUTPUT_PUSHPULL -#undef PAL_MODE_OUTPUT_OPENDRAIN - -/** - * @name STM32-specific I/O mode flags - * @{ - */ -#define PAL_STM32_MODE_MASK (3U << 0U) -#define PAL_STM32_MODE_INPUT (0U << 0U) -#define PAL_STM32_MODE_OUTPUT (1U << 0U) -#define PAL_STM32_MODE_ALTERNATE (2U << 0U) -#define PAL_STM32_MODE_ANALOG (3U << 0U) - -#define PAL_STM32_OTYPE_MASK (1U << 2U) -#define PAL_STM32_OTYPE_PUSHPULL (0U << 2U) -#define PAL_STM32_OTYPE_OPENDRAIN (1U << 2U) - -#define PAL_STM32_OSPEED_MASK (3U << 3U) -#define PAL_STM32_OSPEED_LOWEST (0U << 3U) -#if defined(STM32F0XX) || defined(STM32F30X) || defined(STM32F37X) -#define PAL_STM32_OSPEED_MID (1U << 3U) -#else -#define PAL_STM32_OSPEED_MID1 (1U << 3U) -#define PAL_STM32_OSPEED_MID2 (2U << 3U) -#endif -#define PAL_STM32_OSPEED_HIGHEST (3U << 3U) - -#define PAL_STM32_PUPDR_MASK (3U << 5U) -#define PAL_STM32_PUPDR_FLOATING (0U << 5U) -#define PAL_STM32_PUPDR_PULLUP (1U << 5U) -#define PAL_STM32_PUPDR_PULLDOWN (2U << 5U) - -#define PAL_STM32_ALTERNATE_MASK (15U << 7U) -#define PAL_STM32_ALTERNATE(n) ((n) << 7U) - -/** - * @brief Alternate function. - * - * @param[in] n alternate function selector - */ -#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \ - PAL_STM32_ALTERNATE(n)) -/** @} */ - -/** - * @name Standard I/O mode flags - * @{ - */ -/** - * @brief Implemented as input. - */ -#define PAL_MODE_RESET PAL_STM32_MODE_INPUT - -/** - * @brief Implemented as input with pull-up. - */ -#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP - -/** - * @brief Regular input high-Z pad. - */ -#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT - -/** - * @brief Input pad with weak pull up resistor. - */ -#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \ - PAL_STM32_PUPDR_PULLUP) - -/** - * @brief Input pad with weak pull down resistor. - */ -#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \ - PAL_STM32_PUPDR_PULLDOWN) - -/** - * @brief Analog input mode. - */ -#define PAL_MODE_INPUT_ANALOG PAL_STM32_MODE_ANALOG - -/** - * @brief Push-pull output pad. - */ -#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \ - PAL_STM32_OTYPE_PUSHPULL) - -/** - * @brief Open-drain output pad. - */ -#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \ - PAL_STM32_OTYPE_OPENDRAIN) -/** @} */ - -/*===========================================================================*/ -/* I/O Ports Types and constants. */ -/*===========================================================================*/ - -/** - * @name Port related definitions - * @{ - */ -/** - * @brief Width, in bits, of an I/O port. - */ -#define PAL_IOPORTS_WIDTH 16 - -/** - * @brief Whole port mask. - * @details This macro specifies all the valid bits into a port. - */ -#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) -/** @} */ - -/** - * @name Line handling macros - * @{ - */ -/** - * @brief Forms a line identifier. - * @details A port/pad pair are encoded into an @p ioline_t type. The encoding - * of this type is platform-dependent. - * @note In this driver the pad number is encoded in the lower 4 bits of - * the GPIO address which are guaranteed to be zero. - */ -#define PAL_LINE(port, pad) \ - ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) - -/** - * @brief Decodes a port identifier from a line identifier. - */ -#define PAL_PORT(line) \ - ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U)) - -/** - * @brief Decodes a pad identifier from a line identifier. - */ -#define PAL_PAD(line) \ - ((uint32_t)((uint32_t)(line) & 0x0000000FU)) - -/** - * @brief Value identifying an invalid line. - */ -#define PAL_NOLINE 0U -/** @} */ - -/** - * @brief Type of digital I/O port sized unsigned integer. - */ -typedef uint32_t ioportmask_t; - -/** - * @brief Type of digital I/O modes. - */ -typedef uint32_t iomode_t; - -/** - * @brief Type of an I/O line. - */ -typedef uint32_t ioline_t; - -/** - * @brief Type of an event mode. - */ -typedef uint32_t ioeventmode_t; - -/** - * @brief Type of a port Identifier. - * @details This type can be a scalar or some kind of pointer, do not make - * any assumption about it, use the provided macros when populating - * variables of this type. - */ -typedef stm32_gpio_t * ioportid_t; - -/** - * @brief Type of an pad identifier. - */ -typedef uint32_t iopadid_t; - -/*===========================================================================*/ -/* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ -/*===========================================================================*/ - -/** - * @brief GPIO port A identifier. - */ -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) -#define IOPORT1 GPIOA -#endif - -/** - * @brief GPIO port B identifier. - */ -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) -#define IOPORT2 GPIOB -#endif - -/** - * @brief GPIO port C identifier. - */ -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) -#define IOPORT3 GPIOC -#endif - -/** - * @brief GPIO port D identifier. - */ -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) -#define IOPORT4 GPIOD -#endif - -/** - * @brief GPIO port E identifier. - */ -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) -#define IOPORT5 GPIOE -#endif - -/** - * @brief GPIO port F identifier. - */ -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) -#define IOPORT6 GPIOF -#endif - -/** - * @brief GPIO port G identifier. - */ -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) -#define IOPORT7 GPIOG -#endif - -/** - * @brief GPIO port H identifier. - */ -#if STM32_HAS_GPIOH || defined(__DOXYGEN__) -#define IOPORT8 GPIOH -#endif - -/** - * @brief GPIO port I identifier. - */ -#if STM32_HAS_GPIOI || defined(__DOXYGEN__) -#define IOPORT9 GPIOI -#endif - -/** - * @brief GPIO port J identifier. - */ -#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) -#define IOPORT10 GPIOJ -#endif - -/** - * @brief GPIO port K identifier. - */ -#if STM32_HAS_GPIOK || defined(__DOXYGEN__) -#define IOPORT11 GPIOK -#endif - -/*===========================================================================*/ -/* Implementation, some of the following macros could be implemented as */ -/* functions, if so please put them in pal_lld.c. */ -/*===========================================================================*/ - -/** - * @brief GPIO ports subsystem initialization. - * - * @notapi - */ -#define pal_lld_init() _pal_lld_init() - -/** - * @brief Reads an I/O port. - * @details This function is implemented by reading the GPIO IDR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The port bits. - * - * @notapi - */ -#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR)) - -/** - * @brief Reads the output latch. - * @details This function is implemented by reading the GPIO ODR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The latched logical states. - * - * @notapi - */ -#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR)) - -/** - * @brief Writes on a I/O port. - * @details This function is implemented by writing the GPIO ODR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be written on the specified port - * - * @notapi - */ -#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits)) - -/** - * @brief Sets a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be ORed on the specified port - * - * @notapi - */ -#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits)) - -/** - * @brief Clears a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be cleared on the specified port - * - * @notapi - */ -#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits)) - -/** - * @brief Writes a group of bits. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset the group bit offset within the port - * @param[in] bits bits to be written. Values exceeding the group - * width are masked. - * - * @notapi - */ -#define pal_lld_writegroup(port, mask, offset, bits) { \ - uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \ - ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \ - (port)->BSRR.W = w; \ -} - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset group bit offset within the port - * @param[in] mode group mode - * - * @notapi - */ -#define pal_lld_setgroupmode(port, mask, offset, mode) \ - _pal_lld_setgroupmode(port, mask << offset, mode) - -/** - * @brief Writes a logical state on an output pad. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] bit logical value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @notapi - */ -#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) - -/** - * @brief Pad event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad event mode - * - * @notapi - */ -#define pal_lld_enablepadevent(port, pad, mode) \ - _pal_lld_enablepadevent(port, pad, mode) - -/** - * @brief Pad event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -#define pal_lld_disablepadevent(port, pad) \ - _pal_lld_disablepadevent(port, pad) - -/** - * @brief Returns a PAL event structure associated to a pad. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -#define pal_lld_get_pad_event(port, pad) \ - &_pal_events[pad]; (void)(port) - -/** - * @brief Returns a PAL event structure associated to a line. - * - * @param[in] line line identifier - * - * @notapi - */ -#define pal_lld_get_line_event(line) \ - &_pal_events[PAL_PAD(line)] - -/** - * @brief Pad event enable check. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @return Pad event status. - * @retval false if the pad event is disabled. - * @retval true if the pad event is enabled. - * - * @notapi - */ -#define pal_lld_ispadeventenabled(port, pad) \ - (bool)((EXTI->IMR1 & (1U << (uint32_t)pad)) != 0U) - -#if !defined(__DOXYGEN__) -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) -extern palevent_t _pal_events[16]; -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void _pal_lld_init(void); - void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode); - void _pal_lld_enablepadevent(ioportid_t port, - iopadid_t pad, - ioeventmode_t mode); - void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PAL */ - -#endif /* HAL_PAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv2/hal_pal_lld.h + * @brief STM32 PAL low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef HAL_PAL_LLD_H +#define HAL_PAL_LLD_H + +#include "stm32_gpio.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +/* Specifies palInit() without parameter, required until all platforms will + be updated to the new style.*/ +#define PAL_NEW_INIT + +#undef PAL_MODE_RESET +#undef PAL_MODE_UNCONNECTED +#undef PAL_MODE_INPUT +#undef PAL_MODE_INPUT_PULLUP +#undef PAL_MODE_INPUT_PULLDOWN +#undef PAL_MODE_INPUT_ANALOG +#undef PAL_MODE_OUTPUT_PUSHPULL +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/** + * @name STM32-specific I/O mode flags + * @{ + */ +#define PAL_STM32_MODE_MASK (3U << 0U) +#define PAL_STM32_MODE_INPUT (0U << 0U) +#define PAL_STM32_MODE_OUTPUT (1U << 0U) +#define PAL_STM32_MODE_ALTERNATE (2U << 0U) +#define PAL_STM32_MODE_ANALOG (3U << 0U) + +#define PAL_STM32_OTYPE_MASK (1U << 2U) +#define PAL_STM32_OTYPE_PUSHPULL (0U << 2U) +#define PAL_STM32_OTYPE_OPENDRAIN (1U << 2U) + +#define PAL_STM32_OSPEED_MASK (3U << 3U) +#define PAL_STM32_OSPEED_LOWEST (0U << 3U) +#if defined(STM32F0XX) || defined(STM32F30X) || defined(STM32F37X) +#define PAL_STM32_OSPEED_MID (1U << 3U) +#else +#define PAL_STM32_OSPEED_MID1 (1U << 3U) +#define PAL_STM32_OSPEED_MID2 (2U << 3U) +#endif +#define PAL_STM32_OSPEED_HIGHEST (3U << 3U) + +#define PAL_STM32_PUPDR_MASK (3U << 5U) +#define PAL_STM32_PUPDR_FLOATING (0U << 5U) +#define PAL_STM32_PUPDR_PULLUP (1U << 5U) +#define PAL_STM32_PUPDR_PULLDOWN (2U << 5U) + +#define PAL_STM32_ALTERNATE_MASK (15U << 7U) +#define PAL_STM32_ALTERNATE(n) ((n) << 7U) + +/** + * @brief Alternate function. + * + * @param[in] n alternate function selector + */ +#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \ + PAL_STM32_ALTERNATE(n)) +/** @} */ + +/** + * @name Standard I/O mode flags + * @{ + */ +/** + * @brief Implemented as input. + */ +#define PAL_MODE_RESET PAL_STM32_MODE_INPUT + +/** + * @brief Implemented as input with pull-up. + */ +#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP + +/** + * @brief Regular input high-Z pad. + */ +#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT + +/** + * @brief Input pad with weak pull up resistor. + */ +#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \ + PAL_STM32_PUPDR_PULLUP) + +/** + * @brief Input pad with weak pull down resistor. + */ +#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \ + PAL_STM32_PUPDR_PULLDOWN) + +/** + * @brief Analog input mode. + */ +#define PAL_MODE_INPUT_ANALOG PAL_STM32_MODE_ANALOG + +/** + * @brief Push-pull output pad. + */ +#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \ + PAL_STM32_OTYPE_PUSHPULL) + +/** + * @brief Open-drain output pad. + */ +#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \ + PAL_STM32_OTYPE_OPENDRAIN) +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @name Port related definitions + * @{ + */ +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16 + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) +/** @} */ + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver the pad number is encoded in the lower 4 bits of + * the GPIO address which are guaranteed to be zero. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) + +/** + * @brief Decodes a port identifier from a line identifier. + */ +#define PAL_PORT(line) \ + ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U)) + +/** + * @brief Decodes a pad identifier from a line identifier. + */ +#define PAL_PAD(line) \ + ((uint32_t)((uint32_t)(line) & 0x0000000FU)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0U +/** @} */ + +/** + * @brief Type of digital I/O port sized unsigned integer. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Type of digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Type of an I/O line. + */ +typedef uint32_t ioline_t; + +/** + * @brief Type of an event mode. + */ +typedef uint32_t ioeventmode_t; + +/** + * @brief Type of a port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef stm32_gpio_t * ioportid_t; + +/** + * @brief Type of an pad identifier. + */ +typedef uint32_t iopadid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/* The low level driver wraps the definitions already present in the STM32 */ +/* firmware library. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) +#define IOPORT1 GPIOA +#endif + +/** + * @brief GPIO port B identifier. + */ +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) +#define IOPORT2 GPIOB +#endif + +/** + * @brief GPIO port C identifier. + */ +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) +#define IOPORT3 GPIOC +#endif + +/** + * @brief GPIO port D identifier. + */ +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) +#define IOPORT4 GPIOD +#endif + +/** + * @brief GPIO port E identifier. + */ +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) +#define IOPORT5 GPIOE +#endif + +/** + * @brief GPIO port F identifier. + */ +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) +#define IOPORT6 GPIOF +#endif + +/** + * @brief GPIO port G identifier. + */ +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) +#define IOPORT7 GPIOG +#endif + +/** + * @brief GPIO port H identifier. + */ +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) +#define IOPORT8 GPIOH +#endif + +/** + * @brief GPIO port I identifier. + */ +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) +#define IOPORT9 GPIOI +#endif + +/** + * @brief GPIO port J identifier. + */ +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) +#define IOPORT10 GPIOJ +#endif + +/** + * @brief GPIO port K identifier. + */ +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) +#define IOPORT11 GPIOK +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief GPIO ports subsystem initialization. + * + * @notapi + */ +#define pal_lld_init() _pal_lld_init() + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the GPIO IDR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR)) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the GPIO ODR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR)) + +/** + * @brief Writes on a I/O port. + * @details This function is implemented by writing the GPIO ODR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits)) + +/** + * @brief Writes a group of bits. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group + * width are masked. + * + * @notapi + */ +#define pal_lld_writegroup(port, mask, offset, bits) { \ + uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \ + ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \ + (port)->BSRR.W = w; \ +} + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) + +/** + * @brief Pad event enable. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad event mode + * + * @notapi + */ +#define pal_lld_enablepadevent(port, pad, mode) \ + _pal_lld_enablepadevent(port, pad, mode) + +/** + * @brief Pad event disable. + * @details This function disables previously programmed event callbacks. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_disablepadevent(port, pad) \ + _pal_lld_disablepadevent(port, pad) + +/** + * @brief Returns a PAL event structure associated to a pad. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_get_pad_event(port, pad) \ + &_pal_events[pad]; (void)(port) + +/** + * @brief Returns a PAL event structure associated to a line. + * + * @param[in] line line identifier + * + * @notapi + */ +#define pal_lld_get_line_event(line) \ + &_pal_events[PAL_PAD(line)] + +/** + * @brief Pad event enable check. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return Pad event status. + * @retval false if the pad event is disabled. + * @retval true if the pad event is enabled. + * + * @notapi + */ +#define pal_lld_ispadeventenabled(port, pad) \ + (bool)((EXTI->IMR1 & (1U << (uint32_t)pad)) != 0U) + +#if !defined(__DOXYGEN__) +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) +extern palevent_t _pal_events[16]; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(void); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); + void _pal_lld_enablepadevent(ioportid_t port, + iopadid_t pad, + ioeventmode_t mode); + void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* HAL_PAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h b/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h index 83fd51e7ca..a0a040aabe 100644 --- a/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h +++ b/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h @@ -1,111 +1,111 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv2/stm32_gpio.h - * @brief STM32 GPIO units common header. - * @note This file requires definitions from the ST STM32 header file. - * - * @addtogroup STM32_GPIOv2 - * @{ - */ - -#ifndef STM32_GPIO_H -#define STM32_GPIO_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* Discarded definitions from the ST headers, the PAL driver uses its own - definitions in order to have an unified handling for all devices. - Unfortunately the ST headers have no uniform definitions for the same - objects across the various sub-families.*/ -#undef GPIOA -#undef GPIOB -#undef GPIOC -#undef GPIOD -#undef GPIOE -#undef GPIOF -#undef GPIOG -#undef GPIOH -#undef GPIOI -#undef GPIOJ -#undef GPIOK - -/** - * @name GPIO ports definitions - * @{ - */ -#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) -#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) -#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) -#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) -#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) -#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) -#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) -#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) -#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) -#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE) -#define GPIOK ((stm32_gpio_t *)GPIOK_BASE) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 GPIO registers block. - */ -typedef struct { - - volatile uint32_t MODER; - volatile uint32_t OTYPER; - volatile uint32_t OSPEEDR; - volatile uint32_t PUPDR; - volatile uint32_t IDR; - volatile uint32_t ODR; - volatile union { - uint32_t W; - struct { - uint16_t set; - uint16_t clear; - } H; - } BSRR; - volatile uint32_t LOCKR; - volatile uint32_t AFRL; - volatile uint32_t AFRH; -} stm32_gpio_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* STM32_GPIO_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv2/stm32_gpio.h + * @brief STM32 GPIO units common header. + * @note This file requires definitions from the ST STM32 header file. + * + * @addtogroup STM32_GPIOv2 + * @{ + */ + +#ifndef STM32_GPIO_H +#define STM32_GPIO_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* Discarded definitions from the ST headers, the PAL driver uses its own + definitions in order to have an unified handling for all devices. + Unfortunately the ST headers have no uniform definitions for the same + objects across the various sub-families.*/ +#undef GPIOA +#undef GPIOB +#undef GPIOC +#undef GPIOD +#undef GPIOE +#undef GPIOF +#undef GPIOG +#undef GPIOH +#undef GPIOI +#undef GPIOJ +#undef GPIOK + +/** + * @name GPIO ports definitions + * @{ + */ +#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) +#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) +#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) +#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) +#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) +#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) +#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) +#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) +#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) +#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE) +#define GPIOK ((stm32_gpio_t *)GPIOK_BASE) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 GPIO registers block. + */ +typedef struct { + + volatile uint32_t MODER; + volatile uint32_t OTYPER; + volatile uint32_t OSPEEDR; + volatile uint32_t PUPDR; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile union { + uint32_t W; + struct { + uint16_t set; + uint16_t clear; + } H; + } BSRR; + volatile uint32_t LOCKR; + volatile uint32_t AFRL; + volatile uint32_t AFRH; +} stm32_gpio_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* STM32_GPIO_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv3/driver.mk b/os/hal/ports/STM32/LLD/GPIOv3/driver.mk index b2db0f3139..39e4d7bb75 100644 --- a/os/hal/ports/STM32/LLD/GPIOv3/driver.mk +++ b/os/hal/ports/STM32/LLD/GPIOv3/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3 diff --git a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c index 92b61b52bc..2e748bb651 100644 --- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c +++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c @@ -1,249 +1,249 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv3/hal_pal_lld.c - * @brief STM32 PAL low level driver code. - * - * @addtogroup PAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Event records for the 16 GPIO EXTI channels. - */ -palevent_t _pal_events[16]; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief PAL driver initialization. - * - * @notapi - */ -void _pal_lld_init(void) { - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) - unsigned i; - - for (i = 0; i < 16; i++) { - _pal_init_event(i); - } -#endif -} - -/** - * @brief Pads mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum - * speed. - * - * @param[in] port the port identifier - * @param[in] mask the group mask - * @param[in] mode the mode - * - * @notapi - */ -void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode) { - - uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0; - uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2; - uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3; - uint32_t pupdr = (mode & PAL_STM32_PUPDR_MASK) >> 5; - uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7; - uint32_t ascr = (mode & PAL_STM32_ASCR_MASK) >> 11; - uint32_t lockr = (mode & PAL_STM32_LOCKR_MASK) >> 12; - uint32_t bit = 0; - while (true) { - if ((mask & 1) != 0) { - uint32_t altrmask, m1, m2, m4; - - altrmask = altr << ((bit & 7) * 4); - m1 = 1 << bit; - m2 = 3 << (bit * 2); - m4 = 15 << ((bit & 7) * 4); - port->OTYPER = (port->OTYPER & ~m1) | otyper; - port->ASCR = (port->ASCR & ~m1) | ascr; - port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr; - port->PUPDR = (port->PUPDR & ~m2) | pupdr; - if ((mode & PAL_STM32_MODE_MASK) == PAL_STM32_MODE_ALTERNATE) { - /* If going in alternate mode then the alternate number is set - before switching mode in order to avoid glitches.*/ - if (bit < 8) - port->AFRL = (port->AFRL & ~m4) | altrmask; - else - port->AFRH = (port->AFRH & ~m4) | altrmask; - port->MODER = (port->MODER & ~m2) | moder; - } - else { - /* If going into a non-alternate mode then the mode is switched - before setting the alternate mode in order to avoid glitches.*/ - port->MODER = (port->MODER & ~m2) | moder; - if (bit < 8) - port->AFRL = (port->AFRL & ~m4) | altrmask; - else - port->AFRH = (port->AFRH & ~m4) | altrmask; - } - port->LOCKR = (port->LOCKR & ~m1) | lockr; - } - mask >>= 1; - if (!mask) - return; - otyper <<= 1; - ascr <<= 1; - ospeedr <<= 2; - pupdr <<= 2; - moder <<= 2; - bit++; - } -} - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) -/** - * @brief Pad event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad event mode - * - * @notapi - */ -void _pal_lld_enablepadevent(ioportid_t port, - iopadid_t pad, - ioeventmode_t mode) { - - uint32_t padmask, cridx, croff, crmask, portidx; - - /* Mask of the pad.*/ - padmask = 1U << (uint32_t)pad; - - /* Multiple channel setting of the same channel not allowed, first disable - it. This is done because on STM32 the same channel cannot be mapped on - multiple ports.*/ - osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) && - ((EXTI->FTSR1 & padmask) == 0U), "channel already in use"); - - /* Index and mask of the SYSCFG CR register to be used.*/ - cridx = (uint32_t)pad >> 2U; - croff = ((uint32_t)pad & 3U) * 4U; - crmask = ~(0xFU << croff); - - /* Port index is obtained assuming that GPIO ports are placed at regular - 0x400 intervals in memory space. So far this is true for all devices.*/ - portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; - - /* Port selection in SYSCFG.*/ - SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff); - - /* Programming edge registers.*/ - if (mode & PAL_EVENT_MODE_RISING_EDGE) - EXTI->RTSR1 |= padmask; - else - EXTI->RTSR1 &= ~padmask; - if (mode & PAL_EVENT_MODE_FALLING_EDGE) - EXTI->FTSR1 |= padmask; - else - EXTI->FTSR1 &= ~padmask; - - /* Programming interrupt and event registers.*/ - EXTI->IMR1 |= padmask; - EXTI->EMR1 &= ~padmask; -} - -/** - * @brief Pad event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) { - uint32_t padmask, rtsr1, ftsr1; - - rtsr1 = EXTI->RTSR1; - ftsr1 = EXTI->FTSR1; - - /* Mask of the pad.*/ - padmask = 1U << (uint32_t)pad; - - /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/ - if (((rtsr1 | ftsr1) & padmask) != 0U) { - uint32_t cridx, croff, crport, portidx; - - /* Index and mask of the SYSCFG CR register to be used.*/ - cridx = (uint32_t)pad >> 2U; - croff = ((uint32_t)pad & 3U) * 4U; - - /* Port index is obtained assuming that GPIO ports are placed at regular - 0x400 intervals in memory space. So far this is true for all devices.*/ - portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; - - crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU; - - osalDbgAssert(crport == portidx, "channel mapped on different port"); - - /* Disabling channel.*/ - EXTI->IMR1 &= ~padmask; - EXTI->EMR1 &= ~padmask; - EXTI->RTSR1 = rtsr1 & ~padmask; - EXTI->FTSR1 = ftsr1 & ~padmask; - EXTI->PR1 = padmask; - -#if PAL_USE_CALLBACKS || PAL_USE_WAIT - /* Callback cleared and/or thread reset.*/ - _pal_clear_event(pad); -#endif - } -} -#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */ - -#endif /* HAL_USE_PAL */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv3/hal_pal_lld.c + * @brief STM32 PAL low level driver code. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Event records for the 16 GPIO EXTI channels. + */ +palevent_t _pal_events[16]; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief PAL driver initialization. + * + * @notapi + */ +void _pal_lld_init(void) { + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) + unsigned i; + + for (i = 0; i < 16; i++) { + _pal_init_event(i); + } +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum + * speed. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + + uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0; + uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2; + uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3; + uint32_t pupdr = (mode & PAL_STM32_PUPDR_MASK) >> 5; + uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7; + uint32_t ascr = (mode & PAL_STM32_ASCR_MASK) >> 11; + uint32_t lockr = (mode & PAL_STM32_LOCKR_MASK) >> 12; + uint32_t bit = 0; + while (true) { + if ((mask & 1) != 0) { + uint32_t altrmask, m1, m2, m4; + + altrmask = altr << ((bit & 7) * 4); + m1 = 1 << bit; + m2 = 3 << (bit * 2); + m4 = 15 << ((bit & 7) * 4); + port->OTYPER = (port->OTYPER & ~m1) | otyper; + port->ASCR = (port->ASCR & ~m1) | ascr; + port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr; + port->PUPDR = (port->PUPDR & ~m2) | pupdr; + if ((mode & PAL_STM32_MODE_MASK) == PAL_STM32_MODE_ALTERNATE) { + /* If going in alternate mode then the alternate number is set + before switching mode in order to avoid glitches.*/ + if (bit < 8) + port->AFRL = (port->AFRL & ~m4) | altrmask; + else + port->AFRH = (port->AFRH & ~m4) | altrmask; + port->MODER = (port->MODER & ~m2) | moder; + } + else { + /* If going into a non-alternate mode then the mode is switched + before setting the alternate mode in order to avoid glitches.*/ + port->MODER = (port->MODER & ~m2) | moder; + if (bit < 8) + port->AFRL = (port->AFRL & ~m4) | altrmask; + else + port->AFRH = (port->AFRH & ~m4) | altrmask; + } + port->LOCKR = (port->LOCKR & ~m1) | lockr; + } + mask >>= 1; + if (!mask) + return; + otyper <<= 1; + ascr <<= 1; + ospeedr <<= 2; + pupdr <<= 2; + moder <<= 2; + bit++; + } +} + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Pad event enable. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad event mode + * + * @notapi + */ +void _pal_lld_enablepadevent(ioportid_t port, + iopadid_t pad, + ioeventmode_t mode) { + + uint32_t padmask, cridx, croff, crmask, portidx; + + /* Mask of the pad.*/ + padmask = 1U << (uint32_t)pad; + + /* Multiple channel setting of the same channel not allowed, first disable + it. This is done because on STM32 the same channel cannot be mapped on + multiple ports.*/ + osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) && + ((EXTI->FTSR1 & padmask) == 0U), "channel already in use"); + + /* Index and mask of the SYSCFG CR register to be used.*/ + cridx = (uint32_t)pad >> 2U; + croff = ((uint32_t)pad & 3U) * 4U; + crmask = ~(0xFU << croff); + + /* Port index is obtained assuming that GPIO ports are placed at regular + 0x400 intervals in memory space. So far this is true for all devices.*/ + portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; + + /* Port selection in SYSCFG.*/ + SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff); + + /* Programming edge registers.*/ + if (mode & PAL_EVENT_MODE_RISING_EDGE) + EXTI->RTSR1 |= padmask; + else + EXTI->RTSR1 &= ~padmask; + if (mode & PAL_EVENT_MODE_FALLING_EDGE) + EXTI->FTSR1 |= padmask; + else + EXTI->FTSR1 &= ~padmask; + + /* Programming interrupt and event registers.*/ + EXTI->IMR1 |= padmask; + EXTI->EMR1 &= ~padmask; +} + +/** + * @brief Pad event disable. + * @details This function disables previously programmed event callbacks. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) { + uint32_t padmask, rtsr1, ftsr1; + + rtsr1 = EXTI->RTSR1; + ftsr1 = EXTI->FTSR1; + + /* Mask of the pad.*/ + padmask = 1U << (uint32_t)pad; + + /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/ + if (((rtsr1 | ftsr1) & padmask) != 0U) { + uint32_t cridx, croff, crport, portidx; + + /* Index and mask of the SYSCFG CR register to be used.*/ + cridx = (uint32_t)pad >> 2U; + croff = ((uint32_t)pad & 3U) * 4U; + + /* Port index is obtained assuming that GPIO ports are placed at regular + 0x400 intervals in memory space. So far this is true for all devices.*/ + portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU; + + crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU; + + osalDbgAssert(crport == portidx, "channel mapped on different port"); + + /* Disabling channel.*/ + EXTI->IMR1 &= ~padmask; + EXTI->EMR1 &= ~padmask; + EXTI->RTSR1 = rtsr1 & ~padmask; + EXTI->FTSR1 = ftsr1 & ~padmask; + EXTI->PR1 = padmask; + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT + /* Callback cleared and/or thread reset.*/ + _pal_clear_event(pad); +#endif + } +} +#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */ + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h index 9824257dba..c1f2eb210b 100644 --- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h +++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h @@ -1,554 +1,554 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv3/hal_pal_lld.h - * @brief STM32 PAL low level driver header. - * - * @addtogroup PAL - * @{ - */ - -#ifndef HAL_PAL_LLD_H -#define HAL_PAL_LLD_H - -#include "stm32_gpio.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Unsupported modes and specific modes */ -/*===========================================================================*/ - -/* Specifies palInit() without parameter, required until all platforms will - be updated to the new style.*/ -#define PAL_NEW_INIT - -#undef PAL_MODE_RESET -#undef PAL_MODE_UNCONNECTED -#undef PAL_MODE_INPUT -#undef PAL_MODE_INPUT_PULLUP -#undef PAL_MODE_INPUT_PULLDOWN -#undef PAL_MODE_INPUT_ANALOG -#undef PAL_MODE_OUTPUT_PUSHPULL -#undef PAL_MODE_OUTPUT_OPENDRAIN - -/** - * @name STM32-specific I/O mode flags - * @{ - */ -#define PAL_STM32_MODE_MASK (3U << 0U) -#define PAL_STM32_MODE_INPUT (0U << 0U) -#define PAL_STM32_MODE_OUTPUT (1U << 0U) -#define PAL_STM32_MODE_ALTERNATE (2U << 0U) -#define PAL_STM32_MODE_ANALOG (3U << 0U) - -#define PAL_STM32_OTYPE_MASK (1U << 2U) -#define PAL_STM32_OTYPE_PUSHPULL (0U << 2U) -#define PAL_STM32_OTYPE_OPENDRAIN (1U << 2U) - -#define PAL_STM32_OSPEED_MASK (3U << 3U) -#define PAL_STM32_OSPEED_LOW (0U << 3U) -#define PAL_STM32_OSPEED_MEDIUM (1U << 3U) -#define PAL_STM32_OSPEED_FAST (2U << 3U) -#define PAL_STM32_OSPEED_HIGH (3U << 3U) - -#define PAL_STM32_PUPDR_MASK (3U << 5U) -#define PAL_STM32_PUPDR_FLOATING (0U << 5U) -#define PAL_STM32_PUPDR_PULLUP (1U << 5U) -#define PAL_STM32_PUPDR_PULLDOWN (2U << 5U) - -#define PAL_STM32_ALTERNATE_MASK (15U << 7U) -#define PAL_STM32_ALTERNATE(n) ((n) << 7U) - -#define PAL_STM32_ASCR_MASK (1U << 11U) -#define PAL_STM32_ASCR_OFF (0U << 11U) -#define PAL_STM32_ASCR_ON (1U << 11U) - -#define PAL_STM32_LOCKR_MASK (1U << 12U) -#define PAL_STM32_LOCKR_OFF (0U << 12U) -#define PAL_STM32_LOCKR_ON (1U << 12U) - -/** - * @brief Alternate function. - * - * @param[in] n alternate function selector - */ -#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \ - PAL_STM32_ALTERNATE(n)) -/** @} */ - -/** - * @name Standard I/O mode flags - * @{ - */ -/** - * @brief Implemented as input. - */ -#define PAL_MODE_RESET PAL_STM32_MODE_INPUT - -/** - * @brief Implemented as analog with analog switch disabled and lock. - */ -#define PAL_MODE_UNCONNECTED (PAL_STM32_MODE_ANALOG | \ - PAL_STM32_ASCR_OFF | \ - PAL_STM32_LOCKR_ON) - -/** - * @brief Regular input high-Z pad. - */ -#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT - -/** - * @brief Input pad with weak pull up resistor. - */ -#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \ - PAL_STM32_PUPDR_PULLUP) - -/** - * @brief Input pad with weak pull down resistor. - */ -#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \ - PAL_STM32_PUPDR_PULLDOWN) - -/** - * @brief Analog input mode. - */ -#define PAL_MODE_INPUT_ANALOG (PAL_STM32_MODE_ANALOG | \ - PAL_STM32_ASCR_ON) - -/** - * @brief Push-pull output pad. - */ -#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \ - PAL_STM32_OTYPE_PUSHPULL) - -/** - * @brief Open-drain output pad. - */ -#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \ - PAL_STM32_OTYPE_OPENDRAIN) -/** @} */ - -/* Discarded definitions from the ST headers, the PAL driver uses its own - definitions in order to have an unified handling for all devices. - Unfortunately the ST headers have no uniform definitions for the same - objects across the various sub-families.*/ -#undef GPIOA -#undef GPIOB -#undef GPIOC -#undef GPIOD -#undef GPIOE -#undef GPIOF -#undef GPIOG -#undef GPIOH -#undef GPIOI -#undef GPIOJ -#undef GPIOK - -/** - * @name GPIO ports definitions - * @{ - */ -#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) -#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) -#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) -#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) -#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) -#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) -#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) -#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) -#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) -#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE) -#define GPIOK ((stm32_gpio_t *)GPIOK_BASE) -/** @} */ - -/*===========================================================================*/ -/* I/O Ports Types and constants. */ -/*===========================================================================*/ - -/** - * @name Port related definitions - * @{ - */ -/** - * @brief Width, in bits, of an I/O port. - */ -#define PAL_IOPORTS_WIDTH 16 - -/** - * @brief Whole port mask. - * @details This macro specifies all the valid bits into a port. - */ -#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) -/** @} */ - -/** - * @name Line handling macros - * @{ - */ -/** - * @brief Forms a line identifier. - * @details A port/pad pair are encoded into an @p ioline_t type. The encoding - * of this type is platform-dependent. - * @note In this driver the pad number is encoded in the lower 4 bits of - * the GPIO address which are guaranteed to be zero. - */ -#define PAL_LINE(port, pad) \ - ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) - -/** - * @brief Decodes a port identifier from a line identifier. - */ -#define PAL_PORT(line) \ - ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U)) - -/** - * @brief Decodes a pad identifier from a line identifier. - */ -#define PAL_PAD(line) \ - ((uint32_t)((uint32_t)(line) & 0x0000000FU)) - -/** - * @brief Value identifying an invalid line. - */ -#define PAL_NOLINE 0U -/** @} */ - -/** - * @brief Type of digital I/O port sized unsigned integer. - */ -typedef uint32_t ioportmask_t; - -/** - * @brief Type of digital I/O modes. - */ -typedef uint32_t iomode_t; - -/** - * @brief Type of an I/O line. - */ -typedef uint32_t ioline_t; - -/** - * @brief Type of an event mode. - */ -typedef uint32_t ioeventmode_t; - -/** - * @brief Type of a port Identifier. - * @details This type can be a scalar or some kind of pointer, do not make - * any assumption about it, use the provided macros when populating - * variables of this type. - */ -typedef stm32_gpio_t * ioportid_t; - -/** - * @brief Type of an pad identifier. - */ -typedef uint32_t iopadid_t; - -/*===========================================================================*/ -/* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ -/*===========================================================================*/ - -/** - * @brief GPIO port A identifier. - */ -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) -#define IOPORT1 GPIOA -#endif - -/** - * @brief GPIO port B identifier. - */ -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) -#define IOPORT2 GPIOB -#endif - -/** - * @brief GPIO port C identifier. - */ -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) -#define IOPORT3 GPIOC -#endif - -/** - * @brief GPIO port D identifier. - */ -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) -#define IOPORT4 GPIOD -#endif - -/** - * @brief GPIO port E identifier. - */ -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) -#define IOPORT5 GPIOE -#endif - -/** - * @brief GPIO port F identifier. - */ -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) -#define IOPORT6 GPIOF -#endif - -/** - * @brief GPIO port G identifier. - */ -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) -#define IOPORT7 GPIOG -#endif - -/** - * @brief GPIO port H identifier. - */ -#if STM32_HAS_GPIOH || defined(__DOXYGEN__) -#define IOPORT8 GPIOH -#endif - -/** - * @brief GPIO port I identifier. - */ -#if STM32_HAS_GPIOI || defined(__DOXYGEN__) -#define IOPORT9 GPIOI -#endif - -/** - * @brief GPIO port J identifier. - */ -#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) -#define IOPORT10 GPIOJ -#endif - -/** - * @brief GPIO port K identifier. - */ -#if STM32_HAS_GPIOK || defined(__DOXYGEN__) -#define IOPORT11 GPIOK -#endif - -/*===========================================================================*/ -/* Implementation, some of the following macros could be implemented as */ -/* functions, if so please put them in pal_lld.c. */ -/*===========================================================================*/ - -/** - * @brief GPIO ports subsystem initialization. - * - * @notapi - */ -#define pal_lld_init() _pal_lld_init() - -/** - * @brief Reads an I/O port. - * @details This function is implemented by reading the GPIO IDR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The port bits. - * - * @notapi - */ -#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR)) - -/** - * @brief Reads the output latch. - * @details This function is implemented by reading the GPIO ODR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The latched logical states. - * - * @notapi - */ -#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR)) - -/** - * @brief Writes on a I/O port. - * @details This function is implemented by writing the GPIO ODR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be written on the specified port - * - * @notapi - */ -#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits)) - -/** - * @brief Sets a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be ORed on the specified port - * - * @notapi - */ -#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits)) - -/** - * @brief Clears a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be cleared on the specified port - * - * @notapi - */ -#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits)) - -/** - * @brief Writes a group of bits. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset the group bit offset within the port - * @param[in] bits bits to be written. Values exceeding the group - * width are masked. - * - * @notapi - */ -#define pal_lld_writegroup(port, mask, offset, bits) { \ - uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \ - ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \ - (port)->BSRR.W = w; \ -} - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset group bit offset within the port - * @param[in] mode group mode - * - * @notapi - */ -#define pal_lld_setgroupmode(port, mask, offset, mode) \ - _pal_lld_setgroupmode(port, mask << offset, mode) - -/** - * @brief Writes a logical state on an output pad. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] bit logical value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @notapi - */ -#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) - -/** - * @brief Pad event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad event mode - * - * @notapi - */ -#define pal_lld_enablepadevent(port, pad, mode) \ - _pal_lld_enablepadevent(port, pad, mode) - -/** - * @brief Pad event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -#define pal_lld_disablepadevent(port, pad) \ - _pal_lld_disablepadevent(port, pad) - -/** - * @brief Returns a PAL event structure associated to a pad. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @notapi - */ -#define pal_lld_get_pad_event(port, pad) \ - &_pal_events[pad]; (void)(port) - -/** - * @brief Returns a PAL event structure associated to a line. - * - * @param[in] line line identifier - * - * @notapi - */ -#define pal_lld_get_line_event(line) \ - &_pal_events[PAL_PAD(line)] - -/** - * @brief Pad event enable check. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @return Pad event status. - * @retval false if the pad event is disabled. - * @retval true if the pad event is enabled. - * - * @notapi - */ -#define pal_lld_ispadeventenabled(port, pad) \ - (bool)((EXTI->IMR1 & (1U << (uint32_t)pad)) != 0U) - -#if !defined(__DOXYGEN__) -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) -extern palevent_t _pal_events[16]; -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void _pal_lld_init(void); - void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode); - void _pal_lld_enablepadevent(ioportid_t port, - iopadid_t pad, - ioeventmode_t mode); - void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PAL */ - -#endif /* HAL_PAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv3/hal_pal_lld.h + * @brief STM32 PAL low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef HAL_PAL_LLD_H +#define HAL_PAL_LLD_H + +#include "stm32_gpio.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +/* Specifies palInit() without parameter, required until all platforms will + be updated to the new style.*/ +#define PAL_NEW_INIT + +#undef PAL_MODE_RESET +#undef PAL_MODE_UNCONNECTED +#undef PAL_MODE_INPUT +#undef PAL_MODE_INPUT_PULLUP +#undef PAL_MODE_INPUT_PULLDOWN +#undef PAL_MODE_INPUT_ANALOG +#undef PAL_MODE_OUTPUT_PUSHPULL +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/** + * @name STM32-specific I/O mode flags + * @{ + */ +#define PAL_STM32_MODE_MASK (3U << 0U) +#define PAL_STM32_MODE_INPUT (0U << 0U) +#define PAL_STM32_MODE_OUTPUT (1U << 0U) +#define PAL_STM32_MODE_ALTERNATE (2U << 0U) +#define PAL_STM32_MODE_ANALOG (3U << 0U) + +#define PAL_STM32_OTYPE_MASK (1U << 2U) +#define PAL_STM32_OTYPE_PUSHPULL (0U << 2U) +#define PAL_STM32_OTYPE_OPENDRAIN (1U << 2U) + +#define PAL_STM32_OSPEED_MASK (3U << 3U) +#define PAL_STM32_OSPEED_LOW (0U << 3U) +#define PAL_STM32_OSPEED_MEDIUM (1U << 3U) +#define PAL_STM32_OSPEED_FAST (2U << 3U) +#define PAL_STM32_OSPEED_HIGH (3U << 3U) + +#define PAL_STM32_PUPDR_MASK (3U << 5U) +#define PAL_STM32_PUPDR_FLOATING (0U << 5U) +#define PAL_STM32_PUPDR_PULLUP (1U << 5U) +#define PAL_STM32_PUPDR_PULLDOWN (2U << 5U) + +#define PAL_STM32_ALTERNATE_MASK (15U << 7U) +#define PAL_STM32_ALTERNATE(n) ((n) << 7U) + +#define PAL_STM32_ASCR_MASK (1U << 11U) +#define PAL_STM32_ASCR_OFF (0U << 11U) +#define PAL_STM32_ASCR_ON (1U << 11U) + +#define PAL_STM32_LOCKR_MASK (1U << 12U) +#define PAL_STM32_LOCKR_OFF (0U << 12U) +#define PAL_STM32_LOCKR_ON (1U << 12U) + +/** + * @brief Alternate function. + * + * @param[in] n alternate function selector + */ +#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \ + PAL_STM32_ALTERNATE(n)) +/** @} */ + +/** + * @name Standard I/O mode flags + * @{ + */ +/** + * @brief Implemented as input. + */ +#define PAL_MODE_RESET PAL_STM32_MODE_INPUT + +/** + * @brief Implemented as analog with analog switch disabled and lock. + */ +#define PAL_MODE_UNCONNECTED (PAL_STM32_MODE_ANALOG | \ + PAL_STM32_ASCR_OFF | \ + PAL_STM32_LOCKR_ON) + +/** + * @brief Regular input high-Z pad. + */ +#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT + +/** + * @brief Input pad with weak pull up resistor. + */ +#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \ + PAL_STM32_PUPDR_PULLUP) + +/** + * @brief Input pad with weak pull down resistor. + */ +#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \ + PAL_STM32_PUPDR_PULLDOWN) + +/** + * @brief Analog input mode. + */ +#define PAL_MODE_INPUT_ANALOG (PAL_STM32_MODE_ANALOG | \ + PAL_STM32_ASCR_ON) + +/** + * @brief Push-pull output pad. + */ +#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \ + PAL_STM32_OTYPE_PUSHPULL) + +/** + * @brief Open-drain output pad. + */ +#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \ + PAL_STM32_OTYPE_OPENDRAIN) +/** @} */ + +/* Discarded definitions from the ST headers, the PAL driver uses its own + definitions in order to have an unified handling for all devices. + Unfortunately the ST headers have no uniform definitions for the same + objects across the various sub-families.*/ +#undef GPIOA +#undef GPIOB +#undef GPIOC +#undef GPIOD +#undef GPIOE +#undef GPIOF +#undef GPIOG +#undef GPIOH +#undef GPIOI +#undef GPIOJ +#undef GPIOK + +/** + * @name GPIO ports definitions + * @{ + */ +#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) +#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) +#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) +#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) +#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) +#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) +#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) +#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) +#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) +#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE) +#define GPIOK ((stm32_gpio_t *)GPIOK_BASE) +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @name Port related definitions + * @{ + */ +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16 + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) +/** @} */ + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver the pad number is encoded in the lower 4 bits of + * the GPIO address which are guaranteed to be zero. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) + +/** + * @brief Decodes a port identifier from a line identifier. + */ +#define PAL_PORT(line) \ + ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U)) + +/** + * @brief Decodes a pad identifier from a line identifier. + */ +#define PAL_PAD(line) \ + ((uint32_t)((uint32_t)(line) & 0x0000000FU)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0U +/** @} */ + +/** + * @brief Type of digital I/O port sized unsigned integer. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Type of digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Type of an I/O line. + */ +typedef uint32_t ioline_t; + +/** + * @brief Type of an event mode. + */ +typedef uint32_t ioeventmode_t; + +/** + * @brief Type of a port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef stm32_gpio_t * ioportid_t; + +/** + * @brief Type of an pad identifier. + */ +typedef uint32_t iopadid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/* The low level driver wraps the definitions already present in the STM32 */ +/* firmware library. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) +#define IOPORT1 GPIOA +#endif + +/** + * @brief GPIO port B identifier. + */ +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) +#define IOPORT2 GPIOB +#endif + +/** + * @brief GPIO port C identifier. + */ +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) +#define IOPORT3 GPIOC +#endif + +/** + * @brief GPIO port D identifier. + */ +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) +#define IOPORT4 GPIOD +#endif + +/** + * @brief GPIO port E identifier. + */ +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) +#define IOPORT5 GPIOE +#endif + +/** + * @brief GPIO port F identifier. + */ +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) +#define IOPORT6 GPIOF +#endif + +/** + * @brief GPIO port G identifier. + */ +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) +#define IOPORT7 GPIOG +#endif + +/** + * @brief GPIO port H identifier. + */ +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) +#define IOPORT8 GPIOH +#endif + +/** + * @brief GPIO port I identifier. + */ +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) +#define IOPORT9 GPIOI +#endif + +/** + * @brief GPIO port J identifier. + */ +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) +#define IOPORT10 GPIOJ +#endif + +/** + * @brief GPIO port K identifier. + */ +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) +#define IOPORT11 GPIOK +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief GPIO ports subsystem initialization. + * + * @notapi + */ +#define pal_lld_init() _pal_lld_init() + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the GPIO IDR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR)) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the GPIO ODR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR)) + +/** + * @brief Writes on a I/O port. + * @details This function is implemented by writing the GPIO ODR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits)) + +/** + * @brief Writes a group of bits. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group + * width are masked. + * + * @notapi + */ +#define pal_lld_writegroup(port, mask, offset, bits) { \ + uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \ + ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \ + (port)->BSRR.W = w; \ +} + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) + +/** + * @brief Pad event enable. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad event mode + * + * @notapi + */ +#define pal_lld_enablepadevent(port, pad, mode) \ + _pal_lld_enablepadevent(port, pad, mode) + +/** + * @brief Pad event disable. + * @details This function disables previously programmed event callbacks. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_disablepadevent(port, pad) \ + _pal_lld_disablepadevent(port, pad) + +/** + * @brief Returns a PAL event structure associated to a pad. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_get_pad_event(port, pad) \ + &_pal_events[pad]; (void)(port) + +/** + * @brief Returns a PAL event structure associated to a line. + * + * @param[in] line line identifier + * + * @notapi + */ +#define pal_lld_get_line_event(line) \ + &_pal_events[PAL_PAD(line)] + +/** + * @brief Pad event enable check. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return Pad event status. + * @retval false if the pad event is disabled. + * @retval true if the pad event is enabled. + * + * @notapi + */ +#define pal_lld_ispadeventenabled(port, pad) \ + (bool)((EXTI->IMR1 & (1U << (uint32_t)pad)) != 0U) + +#if !defined(__DOXYGEN__) +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) +extern palevent_t _pal_events[16]; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(void); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); + void _pal_lld_enablepadevent(ioportid_t port, + iopadid_t pad, + ioeventmode_t mode); + void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* HAL_PAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h b/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h index c8ce1df81a..79ffa7ca87 100644 --- a/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h +++ b/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h @@ -1,113 +1,113 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file GPIOv3/stm32_gpio.h - * @brief STM32 GPIO units common header. - * @note This file requires definitions from the ST STM32 header file. - * - * @addtogroup STM32_GPIOv3 - * @{ - */ - -#ifndef STM32_GPIO_H -#define STM32_GPIO_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* Discarded definitions from the ST headers, the PAL driver uses its own - definitions in order to have an unified handling for all devices. - Unfortunately the ST headers have no uniform definitions for the same - objects across the various sub-families.*/ -#undef GPIOA -#undef GPIOB -#undef GPIOC -#undef GPIOD -#undef GPIOE -#undef GPIOF -#undef GPIOG -#undef GPIOH -#undef GPIOI -#undef GPIOJ -#undef GPIOK - -/** - * @name GPIO ports definitions - * @{ - */ -#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) -#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) -#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) -#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) -#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) -#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) -#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) -#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) -#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) -#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE) -#define GPIOK ((stm32_gpio_t *)GPIOK_BASE) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 GPIO registers block. - */ -typedef struct { - - volatile uint32_t MODER; - volatile uint32_t OTYPER; - volatile uint32_t OSPEEDR; - volatile uint32_t PUPDR; - volatile uint32_t IDR; - volatile uint32_t ODR; - volatile union { - uint32_t W; - struct { - uint16_t set; - uint16_t clear; - } H; - } BSRR; - volatile uint32_t LOCKR; - volatile uint32_t AFRL; - volatile uint32_t AFRH; - volatile uint32_t BRR; - volatile uint32_t ASCR; -} stm32_gpio_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* STM32_GPIO_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file GPIOv3/stm32_gpio.h + * @brief STM32 GPIO units common header. + * @note This file requires definitions from the ST STM32 header file. + * + * @addtogroup STM32_GPIOv3 + * @{ + */ + +#ifndef STM32_GPIO_H +#define STM32_GPIO_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* Discarded definitions from the ST headers, the PAL driver uses its own + definitions in order to have an unified handling for all devices. + Unfortunately the ST headers have no uniform definitions for the same + objects across the various sub-families.*/ +#undef GPIOA +#undef GPIOB +#undef GPIOC +#undef GPIOD +#undef GPIOE +#undef GPIOF +#undef GPIOG +#undef GPIOH +#undef GPIOI +#undef GPIOJ +#undef GPIOK + +/** + * @name GPIO ports definitions + * @{ + */ +#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) +#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) +#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) +#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) +#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) +#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) +#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) +#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) +#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) +#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE) +#define GPIOK ((stm32_gpio_t *)GPIOK_BASE) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 GPIO registers block. + */ +typedef struct { + + volatile uint32_t MODER; + volatile uint32_t OTYPER; + volatile uint32_t OSPEEDR; + volatile uint32_t PUPDR; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile union { + uint32_t W; + struct { + uint16_t set; + uint16_t clear; + } H; + } BSRR; + volatile uint32_t LOCKR; + volatile uint32_t AFRL; + volatile uint32_t AFRH; + volatile uint32_t BRR; + volatile uint32_t ASCR; +} stm32_gpio_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* STM32_GPIO_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/I2Cv1/driver.mk b/os/hal/ports/STM32/LLD/I2Cv1/driver.mk index 476dcb8b40..f8cca018e9 100644 --- a/os/hal/ports/STM32/LLD/I2Cv1/driver.mk +++ b/os/hal/ports/STM32/LLD/I2Cv1/driver.mk @@ -1,21 +1,21 @@ -ifeq ($(USE_HAL_I2C_FALLBACK),yes) - # Fallback SW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C -else - # Default HW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1 -endif +ifeq ($(USE_HAL_I2C_FALLBACK),yes) + # Fallback SW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C +else + # Default HW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1 +endif diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c index 3fc2289bd1..833715cf0c 100644 --- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c +++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c @@ -1,889 +1,889 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file I2Cv1/hal_i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define I2C1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_CHN) - -#define I2C1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_CHN) - -#define I2C2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_CHN) - -#define I2C2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_CHN) - -#define I2C3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_CHN) - -#define I2C3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define I2C_EV5_MASTER_MODE_SELECT \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB)) - -#define I2C_EV5_MASTER_MODE_SELECT_NO_BUSY \ - ((uint32_t)((I2C_SR2_MSL << 16) | I2C_SR1_SB)) - -#define I2C_EV6_MASTER_TRA_MODE_SELECTED \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ - I2C_SR1_ADDR | I2C_SR1_TXE)) - -#define I2C_EV6_MASTER_REC_MODE_SELECTED \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR)) - -#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ - I2C_SR1_BTF | I2C_SR1_TXE)) - -#define I2C_EV9_MASTER_ADD10 \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10)) - -#define I2C_EV_MASK 0x00FFFFFF - -#define I2C_ERROR_MASK \ - ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \ - I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT)) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/** @brief I2C3 driver identifier.*/ -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -I2CDriver I2CD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_abort_operation(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Stops the I2C peripheral.*/ - dp->CR1 = I2C_CR1_SWRST; - dp->CR1 = 0; - dp->CR2 = 0; - dp->SR1 = 0; - - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -} - -/** - * @brief Set clock speed. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_set_clock(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint16_t regCCR, clock_div; - int32_t clock_speed = i2cp->config->clock_speed; - i2cdutycycle_t duty = i2cp->config->duty_cycle; - - osalDbgCheck((i2cp != NULL) && - (clock_speed > 0) && - (clock_speed <= 400000)); - - /* CR2 Configuration.*/ - dp->CR2 &= (uint16_t)~I2C_CR2_FREQ; - dp->CR2 |= (uint16_t)I2C_CLK_FREQ; - - /* CCR Configuration.*/ - regCCR = 0; - clock_div = I2C_CCR_CCR; - - if (clock_speed <= 100000) { - /* Configure clock_div in standard mode.*/ - osalDbgAssert(duty == STD_DUTY_CYCLE, "invalid standard mode duty cycle"); - - /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/ - osalDbgAssert((STM32_PCLK1 % (clock_speed * 2)) == 0, - "PCLK1 must be divisible without remainder"); - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); - - osalDbgAssert(clock_div >= 0x04, - "clock divider less then 0x04 not allowed"); - regCCR |= (clock_div & I2C_CCR_CCR); - - /* Sets the Maximum Rise Time for standard mode.*/ - dp->TRISE = I2C_CLK_FREQ + 1; - } - else if (clock_speed <= 400000) { - /* Configure clock_div in fast mode.*/ - osalDbgAssert((duty == FAST_DUTY_CYCLE_2) || - (duty == FAST_DUTY_CYCLE_16_9), - "invalid fast mode duty cycle"); - - if (duty == FAST_DUTY_CYCLE_2) { - /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/ - osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0, - "PCLK1 must be divided without remainder"); - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); - } - else if (duty == FAST_DUTY_CYCLE_16_9) { - /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/ - osalDbgAssert((STM32_PCLK1 % (clock_speed * 25)) == 0, - "PCLK1 must be divided without remainder"); - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); - regCCR |= I2C_CCR_DUTY; - } - - osalDbgAssert(clock_div >= 0x01, - "clock divider less then 0x04 not allowed"); - regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); - - /* Sets the Maximum Rise Time for fast mode.*/ - dp->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1; - } - - osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low"); - - dp->CCR = regCCR; -} - -/** - * @brief Set operation mode of I2C hardware. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_set_opmode(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - i2copmode_t opmode = i2cp->config->op_mode; - uint16_t regCR1; - - regCR1 = dp->CR1; - switch (opmode) { - case OPMODE_I2C: - regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - case OPMODE_SMBUS_DEVICE: - regCR1 |= I2C_CR1_SMBUS; - regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); - break; - case OPMODE_SMBUS_HOST: - regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - } - dp->CR1 = regCR1; -} - -/** - * @brief I2C shared ISR code. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t regSR2 = dp->SR2; - uint32_t event = dp->SR1; - - /* Interrupts are disabled just before dmaStreamEnable() because there - is no need of interrupts until next transaction begin. All the work is - done by the DMA.*/ - switch (I2C_EV_MASK & (event | (regSR2 << 16))) { - case I2C_EV5_MASTER_MODE_SELECT: - case I2C_EV5_MASTER_MODE_SELECT_NO_BUSY: - if ((i2cp->addr >> 8) > 0) { - /* 10-bit address: 1 1 1 1 0 X X R/W */ - dp->DR = 0xF0 | (0x6 & (i2cp->addr >> 8)) | (0x1 & i2cp->addr); - } else { - dp->DR = i2cp->addr; - } - break; - case I2C_EV9_MASTER_ADD10: - /* Set second addr byte (10-bit addressing)*/ - dp->DR = (0xFF & (i2cp->addr >> 1)); - break; - case I2C_EV6_MASTER_REC_MODE_SELECTED: - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dmaStreamEnable(i2cp->dmarx); - dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ - if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2) - dp->CR1 &= ~I2C_CR1_ACK; - break; - case I2C_EV6_MASTER_TRA_MODE_SELECTED: - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dmaStreamEnable(i2cp->dmatx); - break; - case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: - /* Catches BTF event after the end of transmission.*/ - (void)dp->DR; /* clear BTF.*/ - if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) { - /* Starts "read after write" operation, LSB = 1 -> receive.*/ - i2cp->addr |= 0x01; - dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - return; - } - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_STOP; - _i2c_wakeup_isr(i2cp); - break; - default: - break; - } - /* Clear ADDR flag. */ - if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10)) - (void)dp->SR2; - - /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in Master mode.*/ - if (event & I2C_SR1_BERR) { - dp->SR1 &= ~I2C_SR1_BERR; - } -} - -/** - * @brief DMA RX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] flags pre-shifted content of the ISR register - * - * @notapi - */ -static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { - I2C_TypeDef *dp = i2cp->i2c; - - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmarx); - - dp->CR2 &= ~I2C_CR2_LAST; - dp->CR1 &= ~I2C_CR1_ACK; - dp->CR1 |= I2C_CR1_STOP; - _i2c_wakeup_isr(i2cp); -} - -/** - * @brief DMA TX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { - I2C_TypeDef *dp = i2cp->i2c; - - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmatx); - /* Enables interrupts to catch BTF event meaning transmission part complete. - Interrupt handler will decide to generate STOP or to begin receiving part - of R/W transaction itself.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; -} - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] sr content of the SR1 register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { - - /* Clears interrupt flags just to be safe.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - - i2cp->errors = I2C_NO_ERROR; - - if (sr & I2C_SR1_BERR) { /* Bus error. */ - i2cp->errors |= I2C_BUS_ERROR; - /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in - Master mode.*/ - i2cp->i2c->SR1 &= ~I2C_SR1_BERR; - } - - if (sr & I2C_SR1_ARLO) /* Arbitration lost. */ - i2cp->errors |= I2C_ARBITRATION_LOST; - - if (sr & I2C_SR1_AF) { /* Acknowledge fail. */ - i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; - i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ - i2cp->errors |= I2C_ACK_FAILURE; - } - - if (sr & I2C_SR1_OVR) /* Overrun. */ - i2cp->errors |= I2C_OVERRUN; - - if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */ - i2cp->errors |= I2C_TIMEOUT; - - if (sr & I2C_SR1_PECERR) /* PEC error. */ - i2cp->errors |= I2C_PEC_ERROR; - - if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */ - i2cp->errors |= I2C_SMB_ALERT; - - /* If some error has been identified then sends wakes the waiting thread.*/ - if (i2cp->errors != I2C_NO_ERROR) - _i2c_wakeup_error_isr(i2cp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C1 error interrupt handler. - */ -OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { - uint16_t sr = I2CD1.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD1, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C2 error interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { - uint16_t sr = I2CD2.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD2, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -/** - * @brief I2C3 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C3 error interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { - uint16_t sr = I2CD3.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD3, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C3 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; - I2CD1.dmarx = NULL; - I2CD1.dmatx = NULL; -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; - I2CD2.dmarx = NULL; - I2CD2.dmatx = NULL; -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - i2cObjectInit(&I2CD3); - I2CD3.thread = NULL; - I2CD3.i2c = I2C3; - I2CD3.dmarx = NULL; - I2CD3.dmatx = NULL; -#endif /* STM32_I2C_USE_I2C3 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - - i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DIR_P2M; - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - rccResetI2C1(); - - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - rccEnableI2C1(true); - nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - rccResetI2C2(); - - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - rccEnableI2C2(true); - nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - rccResetI2C3(); - - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, - STM32_I2C_I2C3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM, - STM32_I2C_I2C3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - rccEnableI2C3(true); - nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C3 */ - } - - /* I2C registers pointed by the DMA.*/ - dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); - dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); - - /* Reset i2c peripheral.*/ - dp->CR1 = I2C_CR1_SWRST; - dp->CR1 = 0; - dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; - - /* Setup I2C parameters.*/ - i2c_lld_set_clock(i2cp); - i2c_lld_set_opmode(i2cp); - - /* Ready to go.*/ - dp->CR1 |= I2C_CR1_PE; -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state then disables the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - - /* I2C disable.*/ - i2c_lld_abort_operation(i2cp); - dmaStreamFreeI(i2cp->dmatx); - dmaStreamFreeI(i2cp->dmarx); - i2cp->dmatx = NULL; - i2cp->dmarx = NULL; - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - nvicDisableVector(I2C1_EV_IRQn); - nvicDisableVector(I2C1_ER_IRQn); - rccDisableI2C1(); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - nvicDisableVector(I2C2_EV_IRQn); - nvicDisableVector(I2C2_ER_IRQn); - rccDisableI2C2(); - } -#endif - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - nvicDisableVector(I2C3_EV_IRQn); - nvicDisableVector(I2C3_ER_IRQn); - rccDisableI2C3(); - } -#endif - } -} - -/** - * @brief Receives data via the I2C bus as master. - * @details Number of receiving bytes must be more than 1 on STM32F1x. This is - * hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - msg_t msg; - -#if defined(STM32F1XX_I2C) - osalDbgCheck(rxbytes > 1); -#endif - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Initializes driver fields, LSB = 1 -> receive.*/ - i2cp->addr = (addr << 1) | 0x01; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - dmaStreamDisable(i2cp->dmarx); - return MSG_TIMEOUT; - } - - osalSysUnlock(); - } - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - if (msg != MSG_OK) { - dmaStreamDisable(i2cp->dmarx); - } - - return msg; -} - -/** - * @brief Transmits data via the I2C bus as master. - * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. - * This is hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - msg_t msg; - -#if defined(STM32F1XX_I2C) - osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))); -#endif - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Initializes driver fields, LSB = 0 -> transmit.*/ - i2cp->addr = (addr << 1); - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* TX DMA setup.*/ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, txbuf); - dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); - - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - return MSG_TIMEOUT; - } - - osalSysUnlock(); - } - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_START; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - if (msg != MSG_OK) { - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - } - - return msg; -} - -#endif /* HAL_USE_I2C */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file I2Cv1/hal_i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define I2C1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_CHN) + +#define I2C1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_CHN) + +#define I2C2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_CHN) + +#define I2C2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_CHN) + +#define I2C3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_CHN) + +#define I2C3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define I2C_EV5_MASTER_MODE_SELECT \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB)) + +#define I2C_EV5_MASTER_MODE_SELECT_NO_BUSY \ + ((uint32_t)((I2C_SR2_MSL << 16) | I2C_SR1_SB)) + +#define I2C_EV6_MASTER_TRA_MODE_SELECTED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ + I2C_SR1_ADDR | I2C_SR1_TXE)) + +#define I2C_EV6_MASTER_REC_MODE_SELECTED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR)) + +#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ + I2C_SR1_BTF | I2C_SR1_TXE)) + +#define I2C_EV9_MASTER_ADD10 \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10)) + +#define I2C_EV_MASK 0x00FFFFFF + +#define I2C_ERROR_MASK \ + ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \ + I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT)) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/** @brief I2C3 driver identifier.*/ +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_abort_operation(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Stops the I2C peripheral.*/ + dp->CR1 = I2C_CR1_SWRST; + dp->CR1 = 0; + dp->CR2 = 0; + dp->SR1 = 0; + + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +} + +/** + * @brief Set clock speed. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_set_clock(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint16_t regCCR, clock_div; + int32_t clock_speed = i2cp->config->clock_speed; + i2cdutycycle_t duty = i2cp->config->duty_cycle; + + osalDbgCheck((i2cp != NULL) && + (clock_speed > 0) && + (clock_speed <= 400000)); + + /* CR2 Configuration.*/ + dp->CR2 &= (uint16_t)~I2C_CR2_FREQ; + dp->CR2 |= (uint16_t)I2C_CLK_FREQ; + + /* CCR Configuration.*/ + regCCR = 0; + clock_div = I2C_CCR_CCR; + + if (clock_speed <= 100000) { + /* Configure clock_div in standard mode.*/ + osalDbgAssert(duty == STD_DUTY_CYCLE, "invalid standard mode duty cycle"); + + /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/ + osalDbgAssert((STM32_PCLK1 % (clock_speed * 2)) == 0, + "PCLK1 must be divisible without remainder"); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); + + osalDbgAssert(clock_div >= 0x04, + "clock divider less then 0x04 not allowed"); + regCCR |= (clock_div & I2C_CCR_CCR); + + /* Sets the Maximum Rise Time for standard mode.*/ + dp->TRISE = I2C_CLK_FREQ + 1; + } + else if (clock_speed <= 400000) { + /* Configure clock_div in fast mode.*/ + osalDbgAssert((duty == FAST_DUTY_CYCLE_2) || + (duty == FAST_DUTY_CYCLE_16_9), + "invalid fast mode duty cycle"); + + if (duty == FAST_DUTY_CYCLE_2) { + /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/ + osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0, + "PCLK1 must be divided without remainder"); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + } + else if (duty == FAST_DUTY_CYCLE_16_9) { + /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/ + osalDbgAssert((STM32_PCLK1 % (clock_speed * 25)) == 0, + "PCLK1 must be divided without remainder"); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); + regCCR |= I2C_CCR_DUTY; + } + + osalDbgAssert(clock_div >= 0x01, + "clock divider less then 0x04 not allowed"); + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); + + /* Sets the Maximum Rise Time for fast mode.*/ + dp->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1; + } + + osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low"); + + dp->CCR = regCCR; +} + +/** + * @brief Set operation mode of I2C hardware. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_set_opmode(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + i2copmode_t opmode = i2cp->config->op_mode; + uint16_t regCR1; + + regCR1 = dp->CR1; + switch (opmode) { + case OPMODE_I2C: + regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + case OPMODE_SMBUS_DEVICE: + regCR1 |= I2C_CR1_SMBUS; + regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); + break; + case OPMODE_SMBUS_HOST: + regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + } + dp->CR1 = regCR1; +} + +/** + * @brief I2C shared ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t regSR2 = dp->SR2; + uint32_t event = dp->SR1; + + /* Interrupts are disabled just before dmaStreamEnable() because there + is no need of interrupts until next transaction begin. All the work is + done by the DMA.*/ + switch (I2C_EV_MASK & (event | (regSR2 << 16))) { + case I2C_EV5_MASTER_MODE_SELECT: + case I2C_EV5_MASTER_MODE_SELECT_NO_BUSY: + if ((i2cp->addr >> 8) > 0) { + /* 10-bit address: 1 1 1 1 0 X X R/W */ + dp->DR = 0xF0 | (0x6 & (i2cp->addr >> 8)) | (0x1 & i2cp->addr); + } else { + dp->DR = i2cp->addr; + } + break; + case I2C_EV9_MASTER_ADD10: + /* Set second addr byte (10-bit addressing)*/ + dp->DR = (0xFF & (i2cp->addr >> 1)); + break; + case I2C_EV6_MASTER_REC_MODE_SELECTED: + dp->CR2 &= ~I2C_CR2_ITEVTEN; + dmaStreamEnable(i2cp->dmarx); + dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ + if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2) + dp->CR1 &= ~I2C_CR1_ACK; + break; + case I2C_EV6_MASTER_TRA_MODE_SELECTED: + dp->CR2 &= ~I2C_CR2_ITEVTEN; + dmaStreamEnable(i2cp->dmatx); + break; + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: + /* Catches BTF event after the end of transmission.*/ + (void)dp->DR; /* clear BTF.*/ + if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) { + /* Starts "read after write" operation, LSB = 1 -> receive.*/ + i2cp->addr |= 0x01; + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + return; + } + dp->CR2 &= ~I2C_CR2_ITEVTEN; + dp->CR1 |= I2C_CR1_STOP; + _i2c_wakeup_isr(i2cp); + break; + default: + break; + } + /* Clear ADDR flag. */ + if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10)) + (void)dp->SR2; + + /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in Master mode.*/ + if (event & I2C_SR1_BERR) { + dp->SR1 &= ~I2C_SR1_BERR; + } +} + +/** + * @brief DMA RX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] flags pre-shifted content of the ISR register + * + * @notapi + */ +static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { + I2C_TypeDef *dp = i2cp->i2c; + + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmarx); + + dp->CR2 &= ~I2C_CR2_LAST; + dp->CR1 &= ~I2C_CR1_ACK; + dp->CR1 |= I2C_CR1_STOP; + _i2c_wakeup_isr(i2cp); +} + +/** + * @brief DMA TX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { + I2C_TypeDef *dp = i2cp->i2c; + + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmatx); + /* Enables interrupts to catch BTF event meaning transmission part complete. + Interrupt handler will decide to generate STOP or to begin receiving part + of R/W transaction itself.*/ + dp->CR2 |= I2C_CR2_ITEVTEN; +} + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] sr content of the SR1 register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { + + /* Clears interrupt flags just to be safe.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + + i2cp->errors = I2C_NO_ERROR; + + if (sr & I2C_SR1_BERR) { /* Bus error. */ + i2cp->errors |= I2C_BUS_ERROR; + /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in + Master mode.*/ + i2cp->i2c->SR1 &= ~I2C_SR1_BERR; + } + + if (sr & I2C_SR1_ARLO) /* Arbitration lost. */ + i2cp->errors |= I2C_ARBITRATION_LOST; + + if (sr & I2C_SR1_AF) { /* Acknowledge fail. */ + i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; + i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ + i2cp->errors |= I2C_ACK_FAILURE; + } + + if (sr & I2C_SR1_OVR) /* Overrun. */ + i2cp->errors |= I2C_OVERRUN; + + if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */ + i2cp->errors |= I2C_TIMEOUT; + + if (sr & I2C_SR1_PECERR) /* PEC error. */ + i2cp->errors |= I2C_PEC_ERROR; + + if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */ + i2cp->errors |= I2C_SMB_ALERT; + + /* If some error has been identified then sends wakes the waiting thread.*/ + if (i2cp->errors != I2C_NO_ERROR) + _i2c_wakeup_error_isr(i2cp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { + uint16_t sr = I2CD1.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD1, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { + uint16_t sr = I2CD2.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD2, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +/** + * @brief I2C3 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C3 error interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { + uint16_t sr = I2CD3.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD3, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C3 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; + I2CD1.dmarx = NULL; + I2CD1.dmatx = NULL; +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; + I2CD2.dmarx = NULL; + I2CD2.dmatx = NULL; +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + i2cObjectInit(&I2CD3); + I2CD3.thread = NULL; + I2CD3.i2c = I2C3; + I2CD3.dmarx = NULL; + I2CD3.dmatx = NULL; +#endif /* STM32_I2C_USE_I2C3 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + + i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DIR_P2M; + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + rccResetI2C1(); + + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + rccEnableI2C1(true); + nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + rccResetI2C2(); + + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + rccEnableI2C2(true); + nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + rccResetI2C3(); + + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, + STM32_I2C_I2C3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM, + STM32_I2C_I2C3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + rccEnableI2C3(true); + nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C3 */ + } + + /* I2C registers pointed by the DMA.*/ + dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); + dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); + + /* Reset i2c peripheral.*/ + dp->CR1 = I2C_CR1_SWRST; + dp->CR1 = 0; + dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; + + /* Setup I2C parameters.*/ + i2c_lld_set_clock(i2cp); + i2c_lld_set_opmode(i2cp); + + /* Ready to go.*/ + dp->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state then disables the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + + /* I2C disable.*/ + i2c_lld_abort_operation(i2cp); + dmaStreamFreeI(i2cp->dmatx); + dmaStreamFreeI(i2cp->dmarx); + i2cp->dmatx = NULL; + i2cp->dmarx = NULL; + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + nvicDisableVector(I2C1_EV_IRQn); + nvicDisableVector(I2C1_ER_IRQn); + rccDisableI2C1(); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + nvicDisableVector(I2C2_EV_IRQn); + nvicDisableVector(I2C2_ER_IRQn); + rccDisableI2C2(); + } +#endif + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + nvicDisableVector(I2C3_EV_IRQn); + nvicDisableVector(I2C3_ER_IRQn); + rccDisableI2C3(); + } +#endif + } +} + +/** + * @brief Receives data via the I2C bus as master. + * @details Number of receiving bytes must be more than 1 on STM32F1x. This is + * hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + msg_t msg; + +#if defined(STM32F1XX_I2C) + osalDbgCheck(rxbytes > 1); +#endif + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Initializes driver fields, LSB = 1 -> receive.*/ + i2cp->addr = (addr << 1) | 0x01; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + dmaStreamDisable(i2cp->dmarx); + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_ITEVTEN; + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + if (msg != MSG_OK) { + dmaStreamDisable(i2cp->dmarx); + } + + return msg; +} + +/** + * @brief Transmits data via the I2C bus as master. + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. + * This is hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + msg_t msg; + +#if defined(STM32F1XX_I2C) + osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))); +#endif + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Initializes driver fields, LSB = 0 -> transmit.*/ + i2cp->addr = (addr << 1); + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* TX DMA setup.*/ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, txbuf); + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); + + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_ITEVTEN; + dp->CR1 |= I2C_CR1_START; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + if (msg != MSG_OK) { + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + } + + return msg; +} + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h index 1328d47686..5ac9b03cf5 100644 --- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h +++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h @@ -1,513 +1,513 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file I2Cv1/hal_i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef HAL_I2C_LLD_H -#define HAL_I2C_LLD_H - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Peripheral clock frequency. - */ -#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000) - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C3 driver enable switch. - * @details If set to @p TRUE the support for I2C3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C3 FALSE -#endif - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C3 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_IRQ_PRIORITY 10 -#endif - -/** -* @brief I2C1 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** -* @brief I2C2 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** -* @brief I2C3 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for I2C1 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#endif - -/** - * @brief DMA stream used for I2C1 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#endif - -/** - * @brief DMA stream used for I2C2 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for I2C2 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#endif - -/** - * @brief DMA stream used for I2C3 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for I2C3 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -#else /* !STM32_ADVANCED_DMA */ - -/* Fixed streams for platforms using the old DMA peripheral, the values are - valid for both STM32F1xx and STM32L1xx.*/ -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#endif /* !STM32_ADVANCED_DMA*/ - -/* Flag for the whole STM32F1XX family. */ -#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \ - defined(STM32F10X_MD) || defined(STM32F10X_HD) || \ - defined(STM32F10X_XL) || defined(STM32F10X_CL) -#define STM32F1XX_I2C -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 -#error "I2C3 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \ - !STM32_I2C_USE_I2C3 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C3" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) -#error "I2C1 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) -#error "I2C2 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 RX" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 TX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 RX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 TX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 RX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/* Check clock range. */ -#if defined(STM32F4XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32L1XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F2XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD_VL) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ - defined(STM32F10X_CL) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36) -#error "I2C peripheral clock frequency out of range." -#endif -#else -#error "unspecified, unsupported or invalid STM32 platform" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing an I2C address. - */ -typedef uint16_t i2caddr_t; - -/** - * @brief Type of I2C driver condition flags. - */ -typedef uint32_t i2cflags_t; - -/** - * @brief Supported modes for the I2C bus. - */ -typedef enum { - OPMODE_I2C = 1, - OPMODE_SMBUS_DEVICE = 2, - OPMODE_SMBUS_HOST = 3, -} i2copmode_t; - -/** - * @brief Supported duty cycle modes for the I2C bus. - */ -typedef enum { - STD_DUTY_CYCLE = 1, - FAST_DUTY_CYCLE_2 = 2, - FAST_DUTY_CYCLE_16_9 = 3, -} i2cdutycycle_t; - -/** - * @brief Type of I2C driver configuration structure. - */ -typedef struct { - /* End of the mandatory fields.*/ - i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */ - uint32_t clock_speed; /**< @brief Specifies the clock frequency. - @note Must be set to a value lower - than 400kHz. */ - i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode - duty cycle. */ -} I2CConfig; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the bus. - */ - mutex_t mutex; -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; - /** - * @brief Current slave address without R/W bit. - */ - i2caddr_t addr; - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#if STM32_I2C_USE_I2C3 -extern I2CDriver I2CD3; -#endif -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* HAL_I2C_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file I2Cv1/hal_i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef HAL_I2C_LLD_H +#define HAL_I2C_LLD_H + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Peripheral clock frequency. + */ +#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C3 FALSE +#endif + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_IRQ_PRIORITY 10 +#endif + +/** +* @brief I2C1 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** +* @brief I2C2 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** +* @brief I2C3 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for I2C1 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#endif + +/** + * @brief DMA stream used for I2C1 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#endif + +/** + * @brief DMA stream used for I2C2 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for I2C2 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#endif + +/** + * @brief DMA stream used for I2C3 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for I2C3 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +#else /* !STM32_ADVANCED_DMA */ + +/* Fixed streams for platforms using the old DMA peripheral, the values are + valid for both STM32F1xx and STM32L1xx.*/ +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#endif /* !STM32_ADVANCED_DMA*/ + +/* Flag for the whole STM32F1XX family. */ +#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \ + defined(STM32F10X_MD) || defined(STM32F10X_HD) || \ + defined(STM32F10X_XL) || defined(STM32F10X_CL) +#define STM32F1XX_I2C +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \ + !STM32_I2C_USE_I2C3 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C3" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) +#error "I2C1 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) +#error "I2C2 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 RX" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 TX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 RX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 TX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 RX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* Check clock range. */ +#if defined(STM32F4XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32L1XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F2XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD_VL) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ + defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(STM32F10X_CL) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36) +#error "I2C peripheral clock frequency out of range." +#endif +#else +#error "unspecified, unsupported or invalid STM32 platform" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing an I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief Type of I2C driver condition flags. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief Supported modes for the I2C bus. + */ +typedef enum { + OPMODE_I2C = 1, + OPMODE_SMBUS_DEVICE = 2, + OPMODE_SMBUS_HOST = 3, +} i2copmode_t; + +/** + * @brief Supported duty cycle modes for the I2C bus. + */ +typedef enum { + STD_DUTY_CYCLE = 1, + FAST_DUTY_CYCLE_2 = 2, + FAST_DUTY_CYCLE_16_9 = 3, +} i2cdutycycle_t; + +/** + * @brief Type of I2C driver configuration structure. + */ +typedef struct { + /* End of the mandatory fields.*/ + i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */ + uint32_t clock_speed; /**< @brief Specifies the clock frequency. + @note Must be set to a value lower + than 400kHz. */ + i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode + duty cycle. */ +} I2CConfig; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + /** + * @brief Current slave address without R/W bit. + */ + i2caddr_t addr; + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#if STM32_I2C_USE_I2C3 +extern I2CDriver I2CD3; +#endif +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* HAL_I2C_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/I2Cv2/driver.mk b/os/hal/ports/STM32/LLD/I2Cv2/driver.mk index 69b63ced67..06fb82ff8f 100644 --- a/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +++ b/os/hal/ports/STM32/LLD/I2Cv2/driver.mk @@ -1,21 +1,21 @@ -ifeq ($(USE_HAL_I2C_FALLBACK),yes) - # Fallback SW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C -else - # Default HW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2 -endif +ifeq ($(USE_HAL_I2C_FALLBACK),yes) + # Fallback SW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C +else + # Default HW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2 +endif diff --git a/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c index 06c285834a..8ce2be7666 100644 --- a/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c +++ b/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c @@ -1,1169 +1,1169 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file I2Cv2/hal_i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_DMA == TRUE -#define DMAMODE_COMMON \ - (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) - -#define I2C1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_CHN) - -#define I2C1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_CHN) - -#define I2C2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_CHN) - -#define I2C2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_CHN) - -#define I2C3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_CHN) - -#define I2C3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_CHN) - -#define I2C4_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_RX_DMA_STREAM, \ - STM32_I2C4_RX_DMA_CHN) - -#define I2C4_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_TX_DMA_STREAM, \ - STM32_I2C4_TX_DMA_CHN) -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if STM32_I2C_USE_DMA == TRUE -#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx) -#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx) -#else -#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes -#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes -#endif - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define I2C_ERROR_MASK \ - ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ - I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) - -#define I2C_INT_MASK \ - ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ - I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/** @brief I2C3 driver identifier.*/ -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -I2CDriver I2CD3; -#endif - -/** @brief I2C4 driver identifier.*/ -#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) -I2CDriver I2CD4; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Slave address setup. - * @note The RW bit is set to zero internally. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * - * @notapi - */ -static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Address alignment depends on the addressing mode selected.*/ - if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U) - dp->CR2 = (uint32_t)addr << 1U; - else - dp->CR2 = (uint32_t)addr; -} - -/** - * @brief I2C RX transfer setup. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t reload; - size_t n; - - /* The unit can transfer 255 bytes maximum in a single operation.*/ - n = i2c_lld_get_rxbytes(i2cp); - if (n > 255U) { - n = 255U; - reload = I2C_CR2_RELOAD; - } - else { - reload = 0U; - } - - /* Configures the CR2 registers with both the calculated and static - settings.*/ - dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | - I2C_CR2_RD_WRN | (n << 16U) | reload; -} - -/** - * @brief I2C TX transfer setup. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t reload; - size_t n; - - /* The unit can transfer 255 bytes maximum in a single operation.*/ - n = i2c_lld_get_txbytes(i2cp); - if (n > 255U) { - n = 255U; - reload = I2C_CR2_RELOAD; - } - else { - reload = 0U; - } - - /* Configures the CR2 registers with both the calculated and static - settings.*/ - dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | - (n << 16U) | reload; -} - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_abort_operation(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - if (dp->CR1 & I2C_CR1_PE) { - /* Stops the I2C peripheral.*/ - dp->CR1 &= ~I2C_CR1_PE; - while (dp->CR1 & I2C_CR1_PE) - dp->CR1 &= ~I2C_CR1_PE; - dp->CR1 |= I2C_CR1_PE; - } - -#if STM32_I2C_USE_DMA == TRUE - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -#else - dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); -#endif -} - -/** - * @brief I2C shared ISR code. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Special case of a received NACK, the transfer is aborted.*/ - if ((isr & I2C_ISR_NACKF) != 0U) { -#if STM32_I2C_USE_DMA == TRUE - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -#endif - - /* Error flag.*/ - i2cp->errors |= I2C_ACK_FAILURE; - - /* Transaction finished sending the STOP.*/ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more interrupts.*/ - dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE); - - /* Errors are signaled to the upper layer.*/ - _i2c_wakeup_error_isr(i2cp); - - return; - } - -#if STM32_I2C_USE_DMA == FALSE - /* Handling of data transfer if the DMA mode is disabled.*/ - { - uint32_t cr1 = dp->CR1; - - if (i2cp->state == I2C_ACTIVE_TX) { - /* Transmission phase.*/ - if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) { - dp->TXDR = (uint32_t)*i2cp->txptr; - i2cp->txptr++; - i2cp->txbytes--; - if (i2cp->txbytes == 0U) { - dp->CR1 &= ~I2C_CR1_TXIE; - } - } - } - else { - /* Receive phase.*/ - if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { - *i2cp->rxptr = (uint8_t)dp->RXDR; - i2cp->rxptr++; - i2cp->rxbytes--; - if (i2cp->rxbytes == 0U) { - dp->CR1 &= ~I2C_CR1_RXIE; - } - } - } - } -#endif - - /* Partial transfer handling, restarting the transfer and returning.*/ - if ((isr & I2C_ISR_TCR) != 0U) { - if (i2cp->state == I2C_ACTIVE_TX) { - i2c_lld_setup_tx_transfer(i2cp); - } - else { - i2c_lld_setup_rx_transfer(i2cp); - } - return; - } - - /* The following condition is true if a transfer phase has been completed.*/ - if ((isr & I2C_ISR_TC) != 0U) { - if (i2cp->state == I2C_ACTIVE_TX) { - /* End of the transmit phase.*/ - -#if STM32_I2C_USE_DMA == TRUE - /* Disabling TX DMA channel.*/ - dmaStreamDisable(i2cp->dmatx); -#endif - - /* Starting receive phase if necessary.*/ - if (i2c_lld_get_rxbytes(i2cp) > 0U) { - /* Setting up the peripheral.*/ - i2c_lld_setup_rx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling RX DMA.*/ - dmaStreamEnable(i2cp->dmarx); -#else - /* RX interrupt enabled.*/ - dp->CR1 |= I2C_CR1_RXIE; -#endif - - /* Starts the read operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* State change.*/ - i2cp->state = I2C_ACTIVE_RX; - - /* Note, returning because the transaction is not over yet.*/ - return; - } - } - else { - /* End of the receive phase.*/ -#if STM32_I2C_USE_DMA == TRUE - /* Disabling RX DMA channel.*/ - dmaStreamDisable(i2cp->dmarx); -#endif - } - - /* Transaction finished sending the STOP.*/ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more 'Transfer Complete' interrupts.*/ - dp->CR1 &= ~I2C_CR1_TCIE; - - /* Normal transaction end.*/ - _i2c_wakeup_isr(i2cp); - } -} - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { - -#if STM32_I2C_USE_DMA == TRUE - /* Clears DMA interrupt flags just to be safe.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -#else - /* Disabling RX and TX interrupts.*/ - i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); -#endif - - if (isr & I2C_ISR_BERR) - i2cp->errors |= I2C_BUS_ERROR; - - if (isr & I2C_ISR_ARLO) - i2cp->errors |= I2C_ARBITRATION_LOST; - - if (isr & I2C_ISR_OVR) - i2cp->errors |= I2C_OVERRUN; - - if (isr & I2C_ISR_TIMEOUT) - i2cp->errors |= I2C_TIMEOUT; - - /* If some error has been identified then sends wakes the waiting thread.*/ - if (i2cp->errors != I2C_NO_ERROR) - _i2c_wakeup_error_isr(i2cp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD1, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C1 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD2, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C2 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C3 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD3, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C3 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) -#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C4 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD4, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C4 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C4 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; -#if STM32_I2C_USE_DMA == TRUE - I2CD1.dmarx = NULL; - I2CD1.dmatx = NULL; -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; -#if STM32_I2C_USE_DMA == TRUE - I2CD2.dmarx = NULL; - I2CD2.dmatx = NULL; -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - i2cObjectInit(&I2CD3); - I2CD3.thread = NULL; - I2CD3.i2c = I2C3; -#if STM32_I2C_USE_DMA == TRUE - I2CD3.dmarx = NULL; - I2CD3.dmatx = NULL; -#endif -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 - i2cObjectInit(&I2CD4); - I2CD4.thread = NULL; - I2CD4.i2c = I2C4; -#if STM32_I2C_USE_DMA == TRUE - I2CD4.dmarx = NULL; - I2CD4.dmatx = NULL; -#endif -#endif /* STM32_I2C_USE_I2C4 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Make sure I2C peripheral is disabled */ - dp->CR1 &= ~I2C_CR1_PE; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - -#if STM32_I2C_USE_DMA == TRUE - /* Common DMA modes.*/ - i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; -#endif - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - - rccResetI2C1(); - rccEnableI2C1(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, - STM32_I2C_I2C1_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM, - STM32_I2C_I2C1_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C1_RX); - dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C1_TX); -#endif - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#else -#error "I2C1 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - - rccResetI2C2(); - rccEnableI2C2(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, - STM32_I2C_I2C2_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM, - STM32_I2C_I2C2_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C2_RX); - dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C2_TX); -#endif - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#else -#error "I2C2 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - - rccResetI2C3(); - rccEnableI2C3(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, - STM32_I2C_I2C3_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM, - STM32_I2C_I2C3_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C3_RX); - dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C3_TX); -#endif - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); -#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) - nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); -#else -#error "I2C3 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 - if (&I2CD4 == i2cp) { - - rccResetI2C4(); - rccEnableI2C4(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C4_RX_DMA_STREAM, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); - i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C4_TX_DMA_STREAM, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C4_RX); - dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C4_TX); -#endif - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); -#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) - nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); -#else -#error "I2C4 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C4 */ - } - -#if STM32_I2C_USE_DMA == TRUE - /* I2C registers pointed by the DMA.*/ - dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); - dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); -#endif - - /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ - dp->CR1 = i2cp->config->cr1 | -#if STM32_I2C_USE_DMA == TRUE - I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */ -#endif - I2C_CR1_ERRIE | I2C_CR1_NACKIE; - - /* Setup I2C parameters.*/ - dp->TIMINGR = i2cp->config->timingr; - - /* Ready to go.*/ - dp->CR1 |= I2C_CR1_PE; -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state then disables the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - - /* I2C disable.*/ - i2c_lld_abort_operation(i2cp); -#if STM32_I2C_USE_DMA == TRUE - dmaStreamFreeI(i2cp->dmatx); - dmaStreamFreeI(i2cp->dmarx); - i2cp->dmatx = NULL; - i2cp->dmarx = NULL; -#endif - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicDisableVector(STM32_I2C1_EVENT_NUMBER); - nvicDisableVector(STM32_I2C1_ERROR_NUMBER); -#else -#error "I2C1 interrupt numbers not defined" -#endif - - rccDisableI2C1(); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicDisableVector(STM32_I2C2_EVENT_NUMBER); - nvicDisableVector(STM32_I2C2_ERROR_NUMBER); -#else -#error "I2C2 interrupt numbers not defined" -#endif - - rccDisableI2C2(); - } -#endif - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { -#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C3_GLOBAL_NUMBER); -#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) - nvicDisableVector(STM32_I2C3_EVENT_NUMBER); - nvicDisableVector(STM32_I2C3_ERROR_NUMBER); -#else -#error "I2C3 interrupt numbers not defined" -#endif - - rccDisableI2C3(); - } -#endif - -#if STM32_I2C_USE_I2C4 - if (&I2CD4 == i2cp) { -#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C4_GLOBAL_NUMBER); -#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) - nvicDisableVector(STM32_I2C4_EVENT_NUMBER); - nvicDisableVector(STM32_I2C4_ERROR_NUMBER); -#else -#error "I2C4 interrupt numbers not defined" -#endif - - rccDisableI2C4(); - } -#endif - } -} - -/** - * @brief Receives data via the I2C bus as master. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout) { - msg_t msg; - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - -#if STM32_I2C_USE_DMA == TRUE - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); -#else - i2cp->rxptr = rxbuf; - i2cp->rxbytes = rxbytes; -#endif - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if ((dp->ISR & I2C_ISR_BUSY) == 0) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return MSG_TIMEOUT; - } - - osalSysUnlock(); - } - - /* Setting up the slave address.*/ - i2c_lld_set_address(i2cp, addr); - - /* Setting up the peripheral.*/ - i2c_lld_setup_rx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling RX DMA.*/ - dmaStreamEnable(i2cp->dmarx); - - /* Transfer complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; -#else - - /* Transfer complete and RX interrupts enabled.*/ - dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; -#endif - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - - /* In case of a software timeout a STOP is sent as an extreme attempt - to release the bus and DMA is forcibly disabled.*/ - if (msg == MSG_TIMEOUT) { - dp->CR2 |= I2C_CR2_STOP; -#if STM32_I2C_USE_DMA == TRUE - dmaStreamDisable(i2cp->dmarx); -#endif - } - - return msg; -} - -/** - * @brief Transmits data via the I2C bus as master. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout) { - msg_t msg; - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - -#if STM32_I2C_USE_DMA == TRUE - /* TX DMA setup.*/ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, txbuf); - dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); - - /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); -#else - i2cp->txptr = txbuf; - i2cp->txbytes = txbytes; - i2cp->rxptr = rxbuf; - i2cp->rxbytes = rxbytes; -#endif - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if ((dp->ISR & I2C_ISR_BUSY) == 0) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return MSG_TIMEOUT; - } - - osalSysUnlock(); - } - - /* Setting up the slave address.*/ - i2c_lld_set_address(i2cp, addr); - - /* Preparing the transfer.*/ - i2c_lld_setup_tx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling TX DMA.*/ - dmaStreamEnable(i2cp->dmatx); - - /* Transfer complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; -#else - /* Transfer complete and TX interrupts enabled.*/ - dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; -#endif - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - - /* In case of a software timeout a STOP is sent as an extreme attempt - to release the bus and DMA is forcibly disabled.*/ - if (msg == MSG_TIMEOUT) { - dp->CR2 |= I2C_CR2_STOP; -#if STM32_I2C_USE_DMA == TRUE - dmaStreamDisable(i2cp->dmarx); - dmaStreamDisable(i2cp->dmatx); -#endif - } - - return msg; -} - -#endif /* HAL_USE_I2C */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file I2Cv2/hal_i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_DMA == TRUE +#define DMAMODE_COMMON \ + (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) + +#define I2C1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_CHN) + +#define I2C1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_CHN) + +#define I2C2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_CHN) + +#define I2C2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_CHN) + +#define I2C3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_CHN) + +#define I2C3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_CHN) + +#define I2C4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_RX_DMA_STREAM, \ + STM32_I2C4_RX_DMA_CHN) + +#define I2C4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_TX_DMA_STREAM, \ + STM32_I2C4_TX_DMA_CHN) +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if STM32_I2C_USE_DMA == TRUE +#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx) +#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx) +#else +#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes +#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes +#endif + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define I2C_ERROR_MASK \ + ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ + I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) + +#define I2C_INT_MASK \ + ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ + I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/** @brief I2C3 driver identifier.*/ +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD3; +#endif + +/** @brief I2C4 driver identifier.*/ +#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) +I2CDriver I2CD4; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Slave address setup. + * @note The RW bit is set to zero internally. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * + * @notapi + */ +static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Address alignment depends on the addressing mode selected.*/ + if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U) + dp->CR2 = (uint32_t)addr << 1U; + else + dp->CR2 = (uint32_t)addr; +} + +/** + * @brief I2C RX transfer setup. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t reload; + size_t n; + + /* The unit can transfer 255 bytes maximum in a single operation.*/ + n = i2c_lld_get_rxbytes(i2cp); + if (n > 255U) { + n = 255U; + reload = I2C_CR2_RELOAD; + } + else { + reload = 0U; + } + + /* Configures the CR2 registers with both the calculated and static + settings.*/ + dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | + I2C_CR2_RD_WRN | (n << 16U) | reload; +} + +/** + * @brief I2C TX transfer setup. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t reload; + size_t n; + + /* The unit can transfer 255 bytes maximum in a single operation.*/ + n = i2c_lld_get_txbytes(i2cp); + if (n > 255U) { + n = 255U; + reload = I2C_CR2_RELOAD; + } + else { + reload = 0U; + } + + /* Configures the CR2 registers with both the calculated and static + settings.*/ + dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | + (n << 16U) | reload; +} + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_abort_operation(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + if (dp->CR1 & I2C_CR1_PE) { + /* Stops the I2C peripheral.*/ + dp->CR1 &= ~I2C_CR1_PE; + while (dp->CR1 & I2C_CR1_PE) + dp->CR1 &= ~I2C_CR1_PE; + dp->CR1 |= I2C_CR1_PE; + } + +#if STM32_I2C_USE_DMA == TRUE + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +#else + dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); +#endif +} + +/** + * @brief I2C shared ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Special case of a received NACK, the transfer is aborted.*/ + if ((isr & I2C_ISR_NACKF) != 0U) { +#if STM32_I2C_USE_DMA == TRUE + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +#endif + + /* Error flag.*/ + i2cp->errors |= I2C_ACK_FAILURE; + + /* Transaction finished sending the STOP.*/ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more interrupts.*/ + dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE); + + /* Errors are signaled to the upper layer.*/ + _i2c_wakeup_error_isr(i2cp); + + return; + } + +#if STM32_I2C_USE_DMA == FALSE + /* Handling of data transfer if the DMA mode is disabled.*/ + { + uint32_t cr1 = dp->CR1; + + if (i2cp->state == I2C_ACTIVE_TX) { + /* Transmission phase.*/ + if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) { + dp->TXDR = (uint32_t)*i2cp->txptr; + i2cp->txptr++; + i2cp->txbytes--; + if (i2cp->txbytes == 0U) { + dp->CR1 &= ~I2C_CR1_TXIE; + } + } + } + else { + /* Receive phase.*/ + if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { + *i2cp->rxptr = (uint8_t)dp->RXDR; + i2cp->rxptr++; + i2cp->rxbytes--; + if (i2cp->rxbytes == 0U) { + dp->CR1 &= ~I2C_CR1_RXIE; + } + } + } + } +#endif + + /* Partial transfer handling, restarting the transfer and returning.*/ + if ((isr & I2C_ISR_TCR) != 0U) { + if (i2cp->state == I2C_ACTIVE_TX) { + i2c_lld_setup_tx_transfer(i2cp); + } + else { + i2c_lld_setup_rx_transfer(i2cp); + } + return; + } + + /* The following condition is true if a transfer phase has been completed.*/ + if ((isr & I2C_ISR_TC) != 0U) { + if (i2cp->state == I2C_ACTIVE_TX) { + /* End of the transmit phase.*/ + +#if STM32_I2C_USE_DMA == TRUE + /* Disabling TX DMA channel.*/ + dmaStreamDisable(i2cp->dmatx); +#endif + + /* Starting receive phase if necessary.*/ + if (i2c_lld_get_rxbytes(i2cp) > 0U) { + /* Setting up the peripheral.*/ + i2c_lld_setup_rx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling RX DMA.*/ + dmaStreamEnable(i2cp->dmarx); +#else + /* RX interrupt enabled.*/ + dp->CR1 |= I2C_CR1_RXIE; +#endif + + /* Starts the read operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* State change.*/ + i2cp->state = I2C_ACTIVE_RX; + + /* Note, returning because the transaction is not over yet.*/ + return; + } + } + else { + /* End of the receive phase.*/ +#if STM32_I2C_USE_DMA == TRUE + /* Disabling RX DMA channel.*/ + dmaStreamDisable(i2cp->dmarx); +#endif + } + + /* Transaction finished sending the STOP.*/ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more 'Transfer Complete' interrupts.*/ + dp->CR1 &= ~I2C_CR1_TCIE; + + /* Normal transaction end.*/ + _i2c_wakeup_isr(i2cp); + } +} + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { + +#if STM32_I2C_USE_DMA == TRUE + /* Clears DMA interrupt flags just to be safe.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +#else + /* Disabling RX and TX interrupts.*/ + i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); +#endif + + if (isr & I2C_ISR_BERR) + i2cp->errors |= I2C_BUS_ERROR; + + if (isr & I2C_ISR_ARLO) + i2cp->errors |= I2C_ARBITRATION_LOST; + + if (isr & I2C_ISR_OVR) + i2cp->errors |= I2C_OVERRUN; + + if (isr & I2C_ISR_TIMEOUT) + i2cp->errors |= I2C_TIMEOUT; + + /* If some error has been identified then sends wakes the waiting thread.*/ + if (i2cp->errors != I2C_NO_ERROR) + _i2c_wakeup_error_isr(i2cp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD1, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C1 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD2, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C2 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C3 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD3, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C3 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) +#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C4 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD4, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C4 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C4 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; +#if STM32_I2C_USE_DMA == TRUE + I2CD1.dmarx = NULL; + I2CD1.dmatx = NULL; +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; +#if STM32_I2C_USE_DMA == TRUE + I2CD2.dmarx = NULL; + I2CD2.dmatx = NULL; +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + i2cObjectInit(&I2CD3); + I2CD3.thread = NULL; + I2CD3.i2c = I2C3; +#if STM32_I2C_USE_DMA == TRUE + I2CD3.dmarx = NULL; + I2CD3.dmatx = NULL; +#endif +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 + i2cObjectInit(&I2CD4); + I2CD4.thread = NULL; + I2CD4.i2c = I2C4; +#if STM32_I2C_USE_DMA == TRUE + I2CD4.dmarx = NULL; + I2CD4.dmatx = NULL; +#endif +#endif /* STM32_I2C_USE_I2C4 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Make sure I2C peripheral is disabled */ + dp->CR1 &= ~I2C_CR1_PE; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + +#if STM32_I2C_USE_DMA == TRUE + /* Common DMA modes.*/ + i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; +#endif + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + + rccResetI2C1(); + rccEnableI2C1(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, + STM32_I2C_I2C1_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM, + STM32_I2C_I2C1_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C1_RX); + dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C1_TX); +#endif + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#else +#error "I2C1 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + + rccResetI2C2(); + rccEnableI2C2(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, + STM32_I2C_I2C2_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM, + STM32_I2C_I2C2_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C2_RX); + dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C2_TX); +#endif + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#else +#error "I2C2 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + + rccResetI2C3(); + rccEnableI2C3(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, + STM32_I2C_I2C3_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM, + STM32_I2C_I2C3_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C3_RX); + dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C3_TX); +#endif + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); +#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) + nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); +#else +#error "I2C3 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 + if (&I2CD4 == i2cp) { + + rccResetI2C4(); + rccEnableI2C4(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C4_RX_DMA_STREAM, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream"); + i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C4_TX_DMA_STREAM, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C4_RX); + dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C4_TX); +#endif + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); +#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) + nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); +#else +#error "I2C4 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C4 */ + } + +#if STM32_I2C_USE_DMA == TRUE + /* I2C registers pointed by the DMA.*/ + dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); + dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); +#endif + + /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ + dp->CR1 = i2cp->config->cr1 | +#if STM32_I2C_USE_DMA == TRUE + I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */ +#endif + I2C_CR1_ERRIE | I2C_CR1_NACKIE; + + /* Setup I2C parameters.*/ + dp->TIMINGR = i2cp->config->timingr; + + /* Ready to go.*/ + dp->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state then disables the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + + /* I2C disable.*/ + i2c_lld_abort_operation(i2cp); +#if STM32_I2C_USE_DMA == TRUE + dmaStreamFreeI(i2cp->dmatx); + dmaStreamFreeI(i2cp->dmarx); + i2cp->dmatx = NULL; + i2cp->dmarx = NULL; +#endif + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicDisableVector(STM32_I2C1_EVENT_NUMBER); + nvicDisableVector(STM32_I2C1_ERROR_NUMBER); +#else +#error "I2C1 interrupt numbers not defined" +#endif + + rccDisableI2C1(); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicDisableVector(STM32_I2C2_EVENT_NUMBER); + nvicDisableVector(STM32_I2C2_ERROR_NUMBER); +#else +#error "I2C2 interrupt numbers not defined" +#endif + + rccDisableI2C2(); + } +#endif + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { +#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C3_GLOBAL_NUMBER); +#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) + nvicDisableVector(STM32_I2C3_EVENT_NUMBER); + nvicDisableVector(STM32_I2C3_ERROR_NUMBER); +#else +#error "I2C3 interrupt numbers not defined" +#endif + + rccDisableI2C3(); + } +#endif + +#if STM32_I2C_USE_I2C4 + if (&I2CD4 == i2cp) { +#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C4_GLOBAL_NUMBER); +#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) + nvicDisableVector(STM32_I2C4_EVENT_NUMBER); + nvicDisableVector(STM32_I2C4_ERROR_NUMBER); +#else +#error "I2C4 interrupt numbers not defined" +#endif + + rccDisableI2C4(); + } +#endif + } +} + +/** + * @brief Receives data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + msg_t msg; + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + +#if STM32_I2C_USE_DMA == TRUE + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); +#else + i2cp->rxptr = rxbuf; + i2cp->rxbytes = rxbytes; +#endif + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if ((dp->ISR & I2C_ISR_BUSY) == 0) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + /* Setting up the slave address.*/ + i2c_lld_set_address(i2cp, addr); + + /* Setting up the peripheral.*/ + i2c_lld_setup_rx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling RX DMA.*/ + dmaStreamEnable(i2cp->dmarx); + + /* Transfer complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; +#else + + /* Transfer complete and RX interrupts enabled.*/ + dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; +#endif + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + /* In case of a software timeout a STOP is sent as an extreme attempt + to release the bus and DMA is forcibly disabled.*/ + if (msg == MSG_TIMEOUT) { + dp->CR2 |= I2C_CR2_STOP; +#if STM32_I2C_USE_DMA == TRUE + dmaStreamDisable(i2cp->dmarx); +#endif + } + + return msg; +} + +/** + * @brief Transmits data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + msg_t msg; + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + +#if STM32_I2C_USE_DMA == TRUE + /* TX DMA setup.*/ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, txbuf); + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); + + /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); +#else + i2cp->txptr = txbuf; + i2cp->txbytes = txbytes; + i2cp->rxptr = rxbuf; + i2cp->rxbytes = rxbytes; +#endif + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if ((dp->ISR & I2C_ISR_BUSY) == 0) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + /* Setting up the slave address.*/ + i2c_lld_set_address(i2cp, addr); + + /* Preparing the transfer.*/ + i2c_lld_setup_tx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling TX DMA.*/ + dmaStreamEnable(i2cp->dmatx); + + /* Transfer complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; +#else + /* Transfer complete and TX interrupts enabled.*/ + dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; +#endif + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + /* In case of a software timeout a STOP is sent as an extreme attempt + to release the bus and DMA is forcibly disabled.*/ + if (msg == MSG_TIMEOUT) { + dp->CR2 |= I2C_CR2_STOP; +#if STM32_I2C_USE_DMA == TRUE + dmaStreamDisable(i2cp->dmarx); + dmaStreamDisable(i2cp->dmatx); +#endif + } + + return msg; +} + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h b/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h index b1004e793d..453026122c 100644 --- a/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h +++ b/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h @@ -1,509 +1,509 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file I2Cv2/hal_i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef HAL_I2C_LLD_H -#define HAL_I2C_LLD_H - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name TIMINGR register definitions - * @{ - */ -#define STM32_TIMINGR_PRESC_MASK (15U << 28) -#define STM32_TIMINGR_PRESC(n) ((n) << 28) -#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) -#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) -#define STM32_TIMINGR_SDADEL_MASK (15U << 16) -#define STM32_TIMINGR_SDADEL(n) ((n) << 16) -#define STM32_TIMINGR_SCLH_MASK (255U << 8) -#define STM32_TIMINGR_SCLH(n) ((n) << 8) -#define STM32_TIMINGR_SCLL_MASK (255U << 0) -#define STM32_TIMINGR_SCLL(n) ((n) << 0) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C3 driver enable switch. - * @details If set to @p TRUE the support for I2C3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C3 FALSE -#endif - -/** - * @brief I2C4 driver enable switch. - * @details If set to @p TRUE the support for I2C4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C4 FALSE -#endif - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C3 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C4 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C4_IRQ_PRIORITY 10 -#endif - -/** - * @brief DMA use switch. - */ -#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) -#define STM32_I2C_USE_DMA TRUE -#endif - -/** - * @brief I2C1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C4_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 -#error "I2C3 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4 -#error "I2C4 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \ - !STM32_I2C_USE_I2C4 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C4" -#endif - -#if STM32_I2C_USE_DMA == TRUE -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C4" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) -#error "I2C1 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) -#error "I2C2 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C3 && (!defined(STM32_I2C_I2C3_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C3_TX_DMA_STREAM)) -#error "I2C3 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C4 && (!defined(STM32_I2C_I2C4_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C4_TX_DMA_STREAM)) -#error "I2C4 DMA streams not defined" -#endif - -/* Devices without DMAMUX require an additional check.*/ -#if !STM32_DMA_SUPPORTS_DMAMUX - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 RX" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 TX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 RX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 TX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 RX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 TX" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_RX_DMA_STREAM, \ - STM32_I2C4_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C4 RX" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_TX_DMA_STREAM, \ - STM32_I2C4_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C4 TX" -#endif - -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif -#endif /* STM32_I2C_USE_DMA == TRUE */ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing an I2C address. - */ -typedef uint16_t i2caddr_t; - -/** - * @brief Type of I2C driver condition flags. - */ -typedef uint32_t i2cflags_t; - -/** - * @brief Type of I2C driver configuration structure. - */ -typedef struct { - /** - * @brief TIMINGR register initialization. - * @note Refer to the STM32 reference manual, the values are affected - * by the system clock settings in mcuconf.h. - */ - uint32_t timingr; - /** - * @brief CR1 register initialization. - * @note Leave to zero unless you know what you are doing. - */ - uint32_t cr1; - /** - * @brief CR2 register initialization. - * @note Only the ADD10 bit can eventually be specified here. - */ - uint32_t cr2; -} I2CConfig; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - mutex_t mutex; -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; -#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; -#else /* STM32_I2C_USE_DMA == FALSE */ - /** - * @brief Pointer to the next TX buffer location. - */ - const uint8_t *txptr; - /** - * @brief Number of bytes in TX phase. - */ - size_t txbytes; - /** - * @brief Pointer to the next RX buffer location. - */ - uint8_t *rxptr; - /** - * @brief Number of bytes in RX phase. - */ - size_t rxbytes; -#endif /* STM32_I2C_USE_DMA == FALSE */ - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#if STM32_I2C_USE_I2C3 -extern I2CDriver I2CD3; -#endif - -#if STM32_I2C_USE_I2C4 -extern I2CDriver I2CD4; -#endif - -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* HAL_I2C_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file I2Cv2/hal_i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef HAL_I2C_LLD_H +#define HAL_I2C_LLD_H + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name TIMINGR register definitions + * @{ + */ +#define STM32_TIMINGR_PRESC_MASK (15U << 28) +#define STM32_TIMINGR_PRESC(n) ((n) << 28) +#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) +#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) +#define STM32_TIMINGR_SDADEL_MASK (15U << 16) +#define STM32_TIMINGR_SDADEL(n) ((n) << 16) +#define STM32_TIMINGR_SCLH_MASK (255U << 8) +#define STM32_TIMINGR_SCLH(n) ((n) << 8) +#define STM32_TIMINGR_SCLL_MASK (255U << 0) +#define STM32_TIMINGR_SCLL(n) ((n) << 0) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C3 FALSE +#endif + +/** + * @brief I2C4 driver enable switch. + * @details If set to @p TRUE the support for I2C4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C4 FALSE +#endif + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C4 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C4_IRQ_PRIORITY 10 +#endif + +/** + * @brief DMA use switch. + */ +#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) +#define STM32_I2C_USE_DMA TRUE +#endif + +/** + * @brief I2C1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C4_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4 +#error "I2C4 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \ + !STM32_I2C_USE_I2C4 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C4" +#endif + +#if STM32_I2C_USE_DMA == TRUE +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C4" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) +#error "I2C1 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) +#error "I2C2 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C3 && (!defined(STM32_I2C_I2C3_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C3_TX_DMA_STREAM)) +#error "I2C3 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C4 && (!defined(STM32_I2C_I2C4_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C4_TX_DMA_STREAM)) +#error "I2C4 DMA streams not defined" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if !STM32_DMA_SUPPORTS_DMAMUX + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 RX" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 TX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 RX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 TX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 RX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 TX" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_RX_DMA_STREAM, \ + STM32_I2C4_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C4 RX" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_TX_DMA_STREAM, \ + STM32_I2C4_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C4 TX" +#endif + +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif +#endif /* STM32_I2C_USE_DMA == TRUE */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing an I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief Type of I2C driver condition flags. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief Type of I2C driver configuration structure. + */ +typedef struct { + /** + * @brief TIMINGR register initialization. + * @note Refer to the STM32 reference manual, the values are affected + * by the system clock settings in mcuconf.h. + */ + uint32_t timingr; + /** + * @brief CR1 register initialization. + * @note Leave to zero unless you know what you are doing. + */ + uint32_t cr1; + /** + * @brief CR2 register initialization. + * @note Only the ADD10 bit can eventually be specified here. + */ + uint32_t cr2; +} I2CConfig; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; +#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; +#else /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the next TX buffer location. + */ + const uint8_t *txptr; + /** + * @brief Number of bytes in TX phase. + */ + size_t txbytes; + /** + * @brief Pointer to the next RX buffer location. + */ + uint8_t *rxptr; + /** + * @brief Number of bytes in RX phase. + */ + size_t rxbytes; +#endif /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#if STM32_I2C_USE_I2C3 +extern I2CDriver I2CD3; +#endif + +#if STM32_I2C_USE_I2C4 +extern I2CDriver I2CD4; +#endif + +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* HAL_I2C_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/I2Cv3/driver.mk b/os/hal/ports/STM32/LLD/I2Cv3/driver.mk index ef55dfdf89..18db3f65aa 100644 --- a/os/hal/ports/STM32/LLD/I2Cv3/driver.mk +++ b/os/hal/ports/STM32/LLD/I2Cv3/driver.mk @@ -1,21 +1,21 @@ -ifeq ($(USE_HAL_I2C_FALLBACK),yes) - # Fallback SW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C -else - # Default HW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3 -endif +ifeq ($(USE_HAL_I2C_FALLBACK),yes) + # Fallback SW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C +else + # Default HW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3 +endif diff --git a/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c index 24b1ace93e..6786e9161d 100644 --- a/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c +++ b/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c @@ -1,1316 +1,1316 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file I2Cv3/hal_i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_DMA == TRUE - -#if defined(STM32_I2C_DMA_REQUIRED) -#define DMAMODE_COMMON \ - (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) -#endif - -#if defined(STM32_I2C_BDMA_REQUIRED) -#define BDMAMODE_COMMON \ - (STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE | \ - STM32_BDMA_CR_MINC | \ - STM32_BDMA_CR_TEIE | STM32_BDMA_CR_TCIE) -#endif - -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if 0 -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#if defined(STM32_I2C_DMA_REQUIRED) - { - } -#endif -#endif - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define I2C_ERROR_MASK \ - ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ - I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) - -#define I2C_INT_MASK \ - ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ - I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/** @brief I2C3 driver identifier.*/ -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -I2CDriver I2CD3; -#endif - -/** @brief I2C4 driver identifier.*/ -#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) -I2CDriver I2CD4; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_DMA == TRUE -static inline void i2c_lld_start_rx_dma(I2CDriver *i2cp) { - -#if STM32_I2C4_USE_BDMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamEnable(i2cp->rx.bdma); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#endif /* STM32_I2C4_USE_BDMA == TRUE */ -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamEnable(i2cp->rx.dma); - } -#endif -} - -static inline void i2c_lld_start_tx_dma(I2CDriver *i2cp) { - -#if STM32_I2C4_USE_BDMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamEnable(i2cp->tx.bdma); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#endif /* STM32_I2C4_USE_BDMA == TRUE */ -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamEnable(i2cp->tx.dma); - } -#endif -} - -static inline void i2c_lld_stop_rx_dma(I2CDriver *i2cp) { - -#if STM32_I2C4_USE_BDMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamDisable(i2cp->rx.bdma); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#endif /* STM32_I2C4_USE_BDMA == TRUE */ -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamDisable(i2cp->rx.dma); - } -#endif -} - -static inline void i2c_lld_stop_tx_dma(I2CDriver *i2cp) { - -#if STM32_I2C4_USE_BDMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamDisable(i2cp->tx.bdma); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#endif /* STM32_I2C4_USE_BDMA == TRUE */ -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamDisable(i2cp->tx.dma); - } -#endif -} -#endif /* STM32_I2C_USE_DMA == TRUE */ - -/** - * @brief Slave address setup. - * @note The RW bit is set to zero internally. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * - * @notapi - */ -static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Address alignment depends on the addressing mode selected.*/ - if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U) - dp->CR2 = (uint32_t)addr << 1U; - else - dp->CR2 = (uint32_t)addr; -} - -/** - * @brief I2C RX transfer setup. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t reload; - size_t n; - - /* The unit can transfer 255 bytes maximum in a single operation.*/ - n = i2cp->rxbytes; - if (n > 255U) { - n = 255U; - reload = I2C_CR2_RELOAD; - } - else { - reload = 0U; - } - i2cp->rxbytes -= n; - - /* Configures the CR2 registers with both the calculated and static - settings.*/ - dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | - I2C_CR2_RD_WRN | (n << 16U) | reload; -} - -/** - * @brief I2C TX transfer setup. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t reload; - size_t n; - - /* The unit can transfer 255 bytes maximum in a single operation.*/ - n = i2cp->txbytes; - if (n > 255U) { - n = 255U; - reload = I2C_CR2_RELOAD; - } - else { - reload = 0U; - } - i2cp->txbytes -= n; - - /* Configures the CR2 registers with both the calculated and static - settings.*/ - dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | - (n << 16U) | reload; -} - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_abort_operation(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - if (dp->CR1 & I2C_CR1_PE) { - /* Stops the I2C peripheral.*/ - dp->CR1 &= ~I2C_CR1_PE; - while (dp->CR1 & I2C_CR1_PE) - dp->CR1 &= ~I2C_CR1_PE; - dp->CR1 |= I2C_CR1_PE; - } - -#if STM32_I2C_USE_DMA == TRUE - /* Stops the associated DMA streams.*/ - i2c_lld_stop_rx_dma(i2cp); - i2c_lld_stop_tx_dma(i2cp); -#else - dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); -#endif -} - -/** - * @brief I2C shared ISR code. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Special case of a received NACK, the transfer is aborted.*/ - if ((isr & I2C_ISR_NACKF) != 0U) { -#if STM32_I2C_USE_DMA == TRUE - /* Stops the associated DMA streams.*/ - i2c_lld_stop_rx_dma(i2cp); - i2c_lld_stop_tx_dma(i2cp); -#endif - - /* Error flag.*/ - i2cp->errors |= I2C_ACK_FAILURE; - - /* Transaction finished sending the STOP.*/ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more interrupts.*/ - dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE); - - /* Errors are signaled to the upper layer.*/ - _i2c_wakeup_error_isr(i2cp); - - return; - } - -#if STM32_I2C_USE_DMA == FALSE - /* Handling of data transfer if the DMA mode is disabled.*/ - { - uint32_t cr1 = dp->CR1; - - if (i2cp->state == I2C_ACTIVE_TX) { - /* Transmission phase.*/ - if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) { - dp->TXDR = (uint32_t)*i2cp->txptr; - i2cp->txptr++; - i2cp->txbytes--; - if (i2cp->txbytes == 0U) { - dp->CR1 &= ~I2C_CR1_TXIE; - } - } - } - else { - /* Receive phase.*/ - if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { - *i2cp->rxptr = (uint8_t)dp->RXDR; - i2cp->rxptr++; - i2cp->rxbytes--; - if (i2cp->rxbytes == 0U) { - dp->CR1 &= ~I2C_CR1_RXIE; - } - } - } - } -#endif - - /* Partial transfer handling, restarting the transfer and returning.*/ - if ((isr & I2C_ISR_TCR) != 0U) { - if (i2cp->state == I2C_ACTIVE_TX) { - i2c_lld_setup_tx_transfer(i2cp); - } - else { - i2c_lld_setup_rx_transfer(i2cp); - } - return; - } - - /* The following condition is true if a transfer phase has been completed.*/ - if ((isr & I2C_ISR_TC) != 0U) { - if (i2cp->state == I2C_ACTIVE_TX) { - /* End of the transmit phase.*/ - -#if STM32_I2C_USE_DMA == TRUE - /* Disabling TX DMA channel.*/ - i2c_lld_stop_tx_dma(i2cp); -#endif - - /* Starting receive phase if necessary.*/ - if (i2cp->rxbytes > 0U) { - /* Setting up the peripheral.*/ - i2c_lld_setup_rx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling RX DMA.*/ - i2c_lld_start_rx_dma(i2cp); -#else - /* RX interrupt enabled.*/ - dp->CR1 |= I2C_CR1_RXIE; -#endif - - /* Starts the read operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* State change.*/ - i2cp->state = I2C_ACTIVE_RX; - - /* Note, returning because the transaction is not over yet.*/ - return; - } - } - else { - /* End of the receive phase.*/ -#if STM32_I2C_USE_DMA == TRUE - /* Disabling RX DMA channel.*/ - i2c_lld_stop_rx_dma(i2cp); -#endif - } - - /* Transaction finished sending the STOP.*/ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more 'Transfer Complete' interrupts.*/ - dp->CR1 &= ~I2C_CR1_TCIE; - - /* Normal transaction end.*/ - _i2c_wakeup_isr(i2cp); - } -} - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { - -#if STM32_I2C_USE_DMA == TRUE - /* Clears DMA interrupt flags just to be safe.*/ - i2c_lld_stop_rx_dma(i2cp); - i2c_lld_stop_tx_dma(i2cp); -#else - /* Disabling RX and TX interrupts.*/ - i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); -#endif - - if (isr & I2C_ISR_BERR) - i2cp->errors |= I2C_BUS_ERROR; - - if (isr & I2C_ISR_ARLO) - i2cp->errors |= I2C_ARBITRATION_LOST; - - if (isr & I2C_ISR_OVR) - i2cp->errors |= I2C_OVERRUN; - - if (isr & I2C_ISR_TIMEOUT) - i2cp->errors |= I2C_TIMEOUT; - - /* If some error has been identified then wake the waiting thread.*/ - if (i2cp->errors != I2C_NO_ERROR) - _i2c_wakeup_error_isr(i2cp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD1, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C1 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD2, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C2 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C3 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD3, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C3 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) -#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C4 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD4, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C4 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C4 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; -#if STM32_I2C_USE_DMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - I2CD1.is_bdma = false; -#endif - I2CD1.rx.dma = NULL; - I2CD1.tx.dma = NULL; -#endif -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#else -#error "I2C1 interrupt numbers not defined" -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; -#if STM32_I2C_USE_DMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - I2CD2.is_bdma = false; -#endif - I2CD2.rx.dma = NULL; - I2CD2.tx.dma = NULL; -#endif -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#else -#error "I2C2 interrupt numbers not defined" -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - i2cObjectInit(&I2CD3); - I2CD3.thread = NULL; - I2CD3.i2c = I2C3; -#if STM32_I2C_USE_DMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - I2CD3.is_bdma = false; -#endif - I2CD3.rx.dma = NULL; - I2CD3.tx.dma = NULL; -#endif -#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); -#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) - nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); -#else -#error "I2C3 interrupt numbers not defined" -#endif -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 - i2cObjectInit(&I2CD4); - I2CD4.thread = NULL; - I2CD4.i2c = I2C4; -#if STM32_I2C_USE_DMA == TRUE -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) -#if STM32_I2C4_USE_BDMA == TRUE - I2CD4.is_bdma = true; - I2CD4.rx.bdma = NULL; - I2CD4.tx.bdma = NULL; -#else - I2CD4.is_bdma = false; - I2CD4.rx.dma = NULL; - I2CD4.tx.dma = NULL; -#endif /* STM32_I2C4_USE_BDMA == TRUE */ -#endif /* defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) */ -#endif /* STM32_I2C_USE_DMA == TRUE */ -#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); -#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) - nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); -#else -#error "I2C4 interrupt numbers not defined" -#endif -#endif /* STM32_I2C_USE_I2C4 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Make sure I2C peripheral is disabled */ - dp->CR1 &= ~I2C_CR1_PE; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - -#if STM32_I2C_USE_DMA == TRUE - /* Common DMA modes.*/ -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - i2cp->txdmamode = BDMAMODE_COMMON | STM32_BDMA_CR_DIR_M2P; - i2cp->rxdmamode = BDMAMODE_COMMON | STM32_BDMA_CR_DIR_P2M; - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#if defined(STM32_I2C_DMA_REQUIRED) - { - i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; - } -#endif -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - - rccResetI2C1(); - rccEnableI2C1(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, - STM32_I2C_I2C1_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); - i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM, - STM32_I2C_I2C1_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C1_RX); - dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C1_TX); - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - - rccResetI2C2(); - rccEnableI2C2(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, - STM32_I2C_I2C2_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); - i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM, - STM32_I2C_I2C2_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C2_RX); - dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C2_TX); - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - } -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - - rccResetI2C3(); - rccEnableI2C3(true); -#if STM32_I2C_USE_DMA == TRUE - { - i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, - STM32_I2C_I2C3_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); - i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM, - STM32_I2C_I2C3_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C3_RX); - dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C3_TX); - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - } -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 - if (&I2CD4 == i2cp) { - - rccResetI2C4(); - rccEnableI2C4(true); -#if STM32_I2C_USE_DMA == TRUE - { -#if STM32_I2C4_USE_BDMA == TRUE - i2cp->rx.bdma = bdmaStreamAllocI(STM32_I2C_I2C4_RX_BDMA_STREAM, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->rx.bdma != NULL, "unable to allocate stream"); - i2cp->tx.bdma = bdmaStreamAllocI(STM32_I2C_I2C4_TX_BDMA_STREAM, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->tx.bdma != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_BDMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - i2cp->txdmamode |= STM32_BDMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - bdmaSetRequestSource(i2cp->rx.bdma, STM32_DMAMUX2_I2C4_RX); - bdmaSetRequestSource(i2cp->tx.bdma, STM32_DMAMUX2_I2C4_TX); -#else /* STM32_I2C4_USE_BDMA != TRUE */ - i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C4_RX_DMA_STREAM, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); - i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C4_TX_DMA_STREAM, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); - - i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C4_RX); - dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C4_TX); -#endif /* STM32_I2C4_USE_BDMA != TRUE */ - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - } -#endif /* STM32_I2C_USE_I2C4 */ - } - -#if STM32_I2C_USE_DMA == TRUE - /* I2C registers pointed by the DMA.*/ -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamSetPeripheral(i2cp->rx.bdma, &dp->RXDR); - bdmaStreamSetPeripheral(i2cp->tx.bdma, &dp->TXDR); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamSetPeripheral(i2cp->rx.dma, &dp->RXDR); - dmaStreamSetPeripheral(i2cp->tx.dma, &dp->TXDR); - } -#endif -#endif /* STM32_I2C_USE_DMA == TRUE */ - - /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ - dp->CR1 = i2cp->config->cr1 | -#if STM32_I2C_USE_DMA == TRUE - I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */ -#endif - I2C_CR1_ERRIE | I2C_CR1_NACKIE; - - /* Setup I2C parameters.*/ - dp->TIMINGR = i2cp->config->timingr; - - /* Ready to go.*/ - dp->CR1 |= I2C_CR1_PE; -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state then disables the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - - /* I2C disable.*/ - i2c_lld_abort_operation(i2cp); - -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamFreeI(i2cp->rx.bdma); - bdmaStreamFreeI(i2cp->tx.bdma); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamFreeI(i2cp->rx.dma); - dmaStreamFreeI(i2cp->tx.dma); - } -#endif - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - rccDisableI2C1(); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - rccDisableI2C2(); - } -#endif - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - rccDisableI2C3(); - } -#endif - -#if STM32_I2C_USE_I2C4 - if (&I2CD4 == i2cp) { - rccDisableI2C4(); - } -#endif - } -} - -/** - * @brief Receives data via the I2C bus as master. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout) { - msg_t msg; - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* Sizes of transfer phases.*/ - i2cp->txbytes = 0U; - i2cp->rxbytes = rxbytes; - -#if STM32_I2C_USE_DMA == TRUE - /* RX DMA setup.*/ -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamSetMode(i2cp->rx.bdma, i2cp->rxdmamode); - bdmaStreamSetMemory(i2cp->rx.bdma, rxbuf); - bdmaStreamSetTransactionSize(i2cp->rx.bdma, rxbytes); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamSetMode(i2cp->rx.dma, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->rx.dma, rxbuf); - dmaStreamSetTransactionSize(i2cp->rx.dma, rxbytes); - } -#endif -#else - i2cp->rxptr = rxbuf; -#endif - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if ((dp->ISR & I2C_ISR_BUSY) == 0) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return MSG_TIMEOUT; - } - - osalSysUnlock(); - } - - /* Setting up the slave address.*/ - i2c_lld_set_address(i2cp, addr); - - /* Setting up the peripheral.*/ - i2c_lld_setup_rx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling RX DMA.*/ - i2c_lld_start_rx_dma(i2cp); - - /* Transfer complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; -#else - - /* Transfer complete and RX interrupts enabled.*/ - dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; -#endif - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - - /* In case of a software timeout a STOP is sent as an extreme attempt - to release the bus and DMA is forcibly disabled.*/ - if (msg == MSG_TIMEOUT) { - dp->CR2 |= I2C_CR2_STOP; -#if STM32_I2C_USE_DMA == TRUE - i2c_lld_stop_rx_dma(i2cp); -#endif - } - - return msg; -} - -/** - * @brief Transmits data via the I2C bus as master. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout) { - msg_t msg; - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* Sizes of transfer phases.*/ - i2cp->txbytes = txbytes; - i2cp->rxbytes = rxbytes; - -#if STM32_I2C_USE_DMA == TRUE - /* TX and RX DMA setup.*/ -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - if (i2cp->is_bdma) -#endif -#if defined(STM32_I2C_BDMA_REQUIRED) - { - bdmaStreamSetMode(i2cp->tx.bdma, i2cp->txdmamode); - bdmaStreamSetMemory(i2cp->tx.bdma, txbuf); - bdmaStreamSetTransactionSize(i2cp->tx.bdma, txbytes); - - bdmaStreamSetMode(i2cp->rx.bdma, i2cp->rxdmamode); - bdmaStreamSetMemory(i2cp->rx.bdma, rxbuf); - bdmaStreamSetTransactionSize(i2cp->rx.bdma, rxbytes); - } -#endif -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) - else -#endif -#if defined(STM32_I2C_DMA_REQUIRED) - { - dmaStreamSetMode(i2cp->tx.dma, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->tx.dma, txbuf); - dmaStreamSetTransactionSize(i2cp->tx.dma, txbytes); - - dmaStreamSetMode(i2cp->rx.dma, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->rx.dma, rxbuf); - dmaStreamSetTransactionSize(i2cp->rx.dma, rxbytes); - } -#endif -#else - i2cp->txptr = txbuf; - i2cp->rxptr = rxbuf; -#endif - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if ((dp->ISR & I2C_ISR_BUSY) == 0) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { - return MSG_TIMEOUT; - } - - osalSysUnlock(); - } - - /* Setting up the slave address.*/ - i2c_lld_set_address(i2cp, addr); - - /* Preparing the transfer.*/ - i2c_lld_setup_tx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling TX DMA.*/ - i2c_lld_start_tx_dma(i2cp); - - /* Transfer complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; -#else - /* Transfer complete and TX interrupts enabled.*/ - dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; -#endif - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - - /* In case of a software timeout a STOP is sent as an extreme attempt - to release the bus and DMA is forcibly disabled.*/ - if (msg == MSG_TIMEOUT) { - dp->CR2 |= I2C_CR2_STOP; -#if STM32_I2C_USE_DMA == TRUE - i2c_lld_stop_rx_dma(i2cp); - i2c_lld_stop_tx_dma(i2cp); -#endif - } - - return msg; -} - -#endif /* HAL_USE_I2C */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file I2Cv3/hal_i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_DMA == TRUE + +#if defined(STM32_I2C_DMA_REQUIRED) +#define DMAMODE_COMMON \ + (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) +#endif + +#if defined(STM32_I2C_BDMA_REQUIRED) +#define BDMAMODE_COMMON \ + (STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE | \ + STM32_BDMA_CR_MINC | \ + STM32_BDMA_CR_TEIE | STM32_BDMA_CR_TCIE) +#endif + +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if 0 +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#if defined(STM32_I2C_DMA_REQUIRED) + { + } +#endif +#endif + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define I2C_ERROR_MASK \ + ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ + I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) + +#define I2C_INT_MASK \ + ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ + I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/** @brief I2C3 driver identifier.*/ +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD3; +#endif + +/** @brief I2C4 driver identifier.*/ +#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) +I2CDriver I2CD4; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_DMA == TRUE +static inline void i2c_lld_start_rx_dma(I2CDriver *i2cp) { + +#if STM32_I2C4_USE_BDMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamEnable(i2cp->rx.bdma); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#endif /* STM32_I2C4_USE_BDMA == TRUE */ +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamEnable(i2cp->rx.dma); + } +#endif +} + +static inline void i2c_lld_start_tx_dma(I2CDriver *i2cp) { + +#if STM32_I2C4_USE_BDMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamEnable(i2cp->tx.bdma); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#endif /* STM32_I2C4_USE_BDMA == TRUE */ +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamEnable(i2cp->tx.dma); + } +#endif +} + +static inline void i2c_lld_stop_rx_dma(I2CDriver *i2cp) { + +#if STM32_I2C4_USE_BDMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamDisable(i2cp->rx.bdma); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#endif /* STM32_I2C4_USE_BDMA == TRUE */ +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamDisable(i2cp->rx.dma); + } +#endif +} + +static inline void i2c_lld_stop_tx_dma(I2CDriver *i2cp) { + +#if STM32_I2C4_USE_BDMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamDisable(i2cp->tx.bdma); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#endif /* STM32_I2C4_USE_BDMA == TRUE */ +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamDisable(i2cp->tx.dma); + } +#endif +} +#endif /* STM32_I2C_USE_DMA == TRUE */ + +/** + * @brief Slave address setup. + * @note The RW bit is set to zero internally. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * + * @notapi + */ +static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Address alignment depends on the addressing mode selected.*/ + if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U) + dp->CR2 = (uint32_t)addr << 1U; + else + dp->CR2 = (uint32_t)addr; +} + +/** + * @brief I2C RX transfer setup. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t reload; + size_t n; + + /* The unit can transfer 255 bytes maximum in a single operation.*/ + n = i2cp->rxbytes; + if (n > 255U) { + n = 255U; + reload = I2C_CR2_RELOAD; + } + else { + reload = 0U; + } + i2cp->rxbytes -= n; + + /* Configures the CR2 registers with both the calculated and static + settings.*/ + dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | + I2C_CR2_RD_WRN | (n << 16U) | reload; +} + +/** + * @brief I2C TX transfer setup. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t reload; + size_t n; + + /* The unit can transfer 255 bytes maximum in a single operation.*/ + n = i2cp->txbytes; + if (n > 255U) { + n = 255U; + reload = I2C_CR2_RELOAD; + } + else { + reload = 0U; + } + i2cp->txbytes -= n; + + /* Configures the CR2 registers with both the calculated and static + settings.*/ + dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | + (n << 16U) | reload; +} + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_abort_operation(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + if (dp->CR1 & I2C_CR1_PE) { + /* Stops the I2C peripheral.*/ + dp->CR1 &= ~I2C_CR1_PE; + while (dp->CR1 & I2C_CR1_PE) + dp->CR1 &= ~I2C_CR1_PE; + dp->CR1 |= I2C_CR1_PE; + } + +#if STM32_I2C_USE_DMA == TRUE + /* Stops the associated DMA streams.*/ + i2c_lld_stop_rx_dma(i2cp); + i2c_lld_stop_tx_dma(i2cp); +#else + dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); +#endif +} + +/** + * @brief I2C shared ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Special case of a received NACK, the transfer is aborted.*/ + if ((isr & I2C_ISR_NACKF) != 0U) { +#if STM32_I2C_USE_DMA == TRUE + /* Stops the associated DMA streams.*/ + i2c_lld_stop_rx_dma(i2cp); + i2c_lld_stop_tx_dma(i2cp); +#endif + + /* Error flag.*/ + i2cp->errors |= I2C_ACK_FAILURE; + + /* Transaction finished sending the STOP.*/ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more interrupts.*/ + dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE); + + /* Errors are signaled to the upper layer.*/ + _i2c_wakeup_error_isr(i2cp); + + return; + } + +#if STM32_I2C_USE_DMA == FALSE + /* Handling of data transfer if the DMA mode is disabled.*/ + { + uint32_t cr1 = dp->CR1; + + if (i2cp->state == I2C_ACTIVE_TX) { + /* Transmission phase.*/ + if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) { + dp->TXDR = (uint32_t)*i2cp->txptr; + i2cp->txptr++; + i2cp->txbytes--; + if (i2cp->txbytes == 0U) { + dp->CR1 &= ~I2C_CR1_TXIE; + } + } + } + else { + /* Receive phase.*/ + if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { + *i2cp->rxptr = (uint8_t)dp->RXDR; + i2cp->rxptr++; + i2cp->rxbytes--; + if (i2cp->rxbytes == 0U) { + dp->CR1 &= ~I2C_CR1_RXIE; + } + } + } + } +#endif + + /* Partial transfer handling, restarting the transfer and returning.*/ + if ((isr & I2C_ISR_TCR) != 0U) { + if (i2cp->state == I2C_ACTIVE_TX) { + i2c_lld_setup_tx_transfer(i2cp); + } + else { + i2c_lld_setup_rx_transfer(i2cp); + } + return; + } + + /* The following condition is true if a transfer phase has been completed.*/ + if ((isr & I2C_ISR_TC) != 0U) { + if (i2cp->state == I2C_ACTIVE_TX) { + /* End of the transmit phase.*/ + +#if STM32_I2C_USE_DMA == TRUE + /* Disabling TX DMA channel.*/ + i2c_lld_stop_tx_dma(i2cp); +#endif + + /* Starting receive phase if necessary.*/ + if (i2cp->rxbytes > 0U) { + /* Setting up the peripheral.*/ + i2c_lld_setup_rx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling RX DMA.*/ + i2c_lld_start_rx_dma(i2cp); +#else + /* RX interrupt enabled.*/ + dp->CR1 |= I2C_CR1_RXIE; +#endif + + /* Starts the read operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* State change.*/ + i2cp->state = I2C_ACTIVE_RX; + + /* Note, returning because the transaction is not over yet.*/ + return; + } + } + else { + /* End of the receive phase.*/ +#if STM32_I2C_USE_DMA == TRUE + /* Disabling RX DMA channel.*/ + i2c_lld_stop_rx_dma(i2cp); +#endif + } + + /* Transaction finished sending the STOP.*/ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more 'Transfer Complete' interrupts.*/ + dp->CR1 &= ~I2C_CR1_TCIE; + + /* Normal transaction end.*/ + _i2c_wakeup_isr(i2cp); + } +} + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { + +#if STM32_I2C_USE_DMA == TRUE + /* Clears DMA interrupt flags just to be safe.*/ + i2c_lld_stop_rx_dma(i2cp); + i2c_lld_stop_tx_dma(i2cp); +#else + /* Disabling RX and TX interrupts.*/ + i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); +#endif + + if (isr & I2C_ISR_BERR) + i2cp->errors |= I2C_BUS_ERROR; + + if (isr & I2C_ISR_ARLO) + i2cp->errors |= I2C_ARBITRATION_LOST; + + if (isr & I2C_ISR_OVR) + i2cp->errors |= I2C_OVERRUN; + + if (isr & I2C_ISR_TIMEOUT) + i2cp->errors |= I2C_TIMEOUT; + + /* If some error has been identified then wake the waiting thread.*/ + if (i2cp->errors != I2C_NO_ERROR) + _i2c_wakeup_error_isr(i2cp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD1, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C1 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD2, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C2 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C3 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD3, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C3 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) +#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C4 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD4, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C4 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C4 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; +#if STM32_I2C_USE_DMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + I2CD1.is_bdma = false; +#endif + I2CD1.rx.dma = NULL; + I2CD1.tx.dma = NULL; +#endif +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#else +#error "I2C1 interrupt numbers not defined" +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; +#if STM32_I2C_USE_DMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + I2CD2.is_bdma = false; +#endif + I2CD2.rx.dma = NULL; + I2CD2.tx.dma = NULL; +#endif +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#else +#error "I2C2 interrupt numbers not defined" +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + i2cObjectInit(&I2CD3); + I2CD3.thread = NULL; + I2CD3.i2c = I2C3; +#if STM32_I2C_USE_DMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + I2CD3.is_bdma = false; +#endif + I2CD3.rx.dma = NULL; + I2CD3.tx.dma = NULL; +#endif +#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); +#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) + nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); +#else +#error "I2C3 interrupt numbers not defined" +#endif +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 + i2cObjectInit(&I2CD4); + I2CD4.thread = NULL; + I2CD4.i2c = I2C4; +#if STM32_I2C_USE_DMA == TRUE +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) +#if STM32_I2C4_USE_BDMA == TRUE + I2CD4.is_bdma = true; + I2CD4.rx.bdma = NULL; + I2CD4.tx.bdma = NULL; +#else + I2CD4.is_bdma = false; + I2CD4.rx.dma = NULL; + I2CD4.tx.dma = NULL; +#endif /* STM32_I2C4_USE_BDMA == TRUE */ +#endif /* defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) */ +#endif /* STM32_I2C_USE_DMA == TRUE */ +#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); +#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) + nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); +#else +#error "I2C4 interrupt numbers not defined" +#endif +#endif /* STM32_I2C_USE_I2C4 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Make sure I2C peripheral is disabled */ + dp->CR1 &= ~I2C_CR1_PE; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + +#if STM32_I2C_USE_DMA == TRUE + /* Common DMA modes.*/ +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + i2cp->txdmamode = BDMAMODE_COMMON | STM32_BDMA_CR_DIR_M2P; + i2cp->rxdmamode = BDMAMODE_COMMON | STM32_BDMA_CR_DIR_P2M; + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#if defined(STM32_I2C_DMA_REQUIRED) + { + i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; + } +#endif +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + + rccResetI2C1(); + rccEnableI2C1(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM, + STM32_I2C_I2C1_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); + i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM, + STM32_I2C_I2C1_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C1_RX); + dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C1_TX); + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + + rccResetI2C2(); + rccEnableI2C2(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM, + STM32_I2C_I2C2_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); + i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM, + STM32_I2C_I2C2_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C2_RX); + dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C2_TX); + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + } +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + + rccResetI2C3(); + rccEnableI2C3(true); +#if STM32_I2C_USE_DMA == TRUE + { + i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM, + STM32_I2C_I2C3_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); + i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM, + STM32_I2C_I2C3_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C3_RX); + dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C3_TX); + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + } +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 + if (&I2CD4 == i2cp) { + + rccResetI2C4(); + rccEnableI2C4(true); +#if STM32_I2C_USE_DMA == TRUE + { +#if STM32_I2C4_USE_BDMA == TRUE + i2cp->rx.bdma = bdmaStreamAllocI(STM32_I2C_I2C4_RX_BDMA_STREAM, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->rx.bdma != NULL, "unable to allocate stream"); + i2cp->tx.bdma = bdmaStreamAllocI(STM32_I2C_I2C4_TX_BDMA_STREAM, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->tx.bdma != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_BDMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + i2cp->txdmamode |= STM32_BDMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + bdmaSetRequestSource(i2cp->rx.bdma, STM32_DMAMUX2_I2C4_RX); + bdmaSetRequestSource(i2cp->tx.bdma, STM32_DMAMUX2_I2C4_TX); +#else /* STM32_I2C4_USE_BDMA != TRUE */ + i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C4_RX_DMA_STREAM, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream"); + i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C4_TX_DMA_STREAM, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream"); + + i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C4_RX); + dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C4_TX); +#endif /* STM32_I2C4_USE_BDMA != TRUE */ + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + } +#endif /* STM32_I2C_USE_I2C4 */ + } + +#if STM32_I2C_USE_DMA == TRUE + /* I2C registers pointed by the DMA.*/ +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamSetPeripheral(i2cp->rx.bdma, &dp->RXDR); + bdmaStreamSetPeripheral(i2cp->tx.bdma, &dp->TXDR); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamSetPeripheral(i2cp->rx.dma, &dp->RXDR); + dmaStreamSetPeripheral(i2cp->tx.dma, &dp->TXDR); + } +#endif +#endif /* STM32_I2C_USE_DMA == TRUE */ + + /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ + dp->CR1 = i2cp->config->cr1 | +#if STM32_I2C_USE_DMA == TRUE + I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */ +#endif + I2C_CR1_ERRIE | I2C_CR1_NACKIE; + + /* Setup I2C parameters.*/ + dp->TIMINGR = i2cp->config->timingr; + + /* Ready to go.*/ + dp->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state then disables the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + + /* I2C disable.*/ + i2c_lld_abort_operation(i2cp); + +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamFreeI(i2cp->rx.bdma); + bdmaStreamFreeI(i2cp->tx.bdma); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamFreeI(i2cp->rx.dma); + dmaStreamFreeI(i2cp->tx.dma); + } +#endif + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + rccDisableI2C1(); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + rccDisableI2C2(); + } +#endif + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + rccDisableI2C3(); + } +#endif + +#if STM32_I2C_USE_I2C4 + if (&I2CD4 == i2cp) { + rccDisableI2C4(); + } +#endif + } +} + +/** + * @brief Receives data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + msg_t msg; + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* Sizes of transfer phases.*/ + i2cp->txbytes = 0U; + i2cp->rxbytes = rxbytes; + +#if STM32_I2C_USE_DMA == TRUE + /* RX DMA setup.*/ +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamSetMode(i2cp->rx.bdma, i2cp->rxdmamode); + bdmaStreamSetMemory(i2cp->rx.bdma, rxbuf); + bdmaStreamSetTransactionSize(i2cp->rx.bdma, rxbytes); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamSetMode(i2cp->rx.dma, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->rx.dma, rxbuf); + dmaStreamSetTransactionSize(i2cp->rx.dma, rxbytes); + } +#endif +#else + i2cp->rxptr = rxbuf; +#endif + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if ((dp->ISR & I2C_ISR_BUSY) == 0) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + /* Setting up the slave address.*/ + i2c_lld_set_address(i2cp, addr); + + /* Setting up the peripheral.*/ + i2c_lld_setup_rx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling RX DMA.*/ + i2c_lld_start_rx_dma(i2cp); + + /* Transfer complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; +#else + + /* Transfer complete and RX interrupts enabled.*/ + dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; +#endif + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + /* In case of a software timeout a STOP is sent as an extreme attempt + to release the bus and DMA is forcibly disabled.*/ + if (msg == MSG_TIMEOUT) { + dp->CR2 |= I2C_CR2_STOP; +#if STM32_I2C_USE_DMA == TRUE + i2c_lld_stop_rx_dma(i2cp); +#endif + } + + return msg; +} + +/** + * @brief Transmits data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + msg_t msg; + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* Sizes of transfer phases.*/ + i2cp->txbytes = txbytes; + i2cp->rxbytes = rxbytes; + +#if STM32_I2C_USE_DMA == TRUE + /* TX and RX DMA setup.*/ +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + if (i2cp->is_bdma) +#endif +#if defined(STM32_I2C_BDMA_REQUIRED) + { + bdmaStreamSetMode(i2cp->tx.bdma, i2cp->txdmamode); + bdmaStreamSetMemory(i2cp->tx.bdma, txbuf); + bdmaStreamSetTransactionSize(i2cp->tx.bdma, txbytes); + + bdmaStreamSetMode(i2cp->rx.bdma, i2cp->rxdmamode); + bdmaStreamSetMemory(i2cp->rx.bdma, rxbuf); + bdmaStreamSetTransactionSize(i2cp->rx.bdma, rxbytes); + } +#endif +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) + else +#endif +#if defined(STM32_I2C_DMA_REQUIRED) + { + dmaStreamSetMode(i2cp->tx.dma, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->tx.dma, txbuf); + dmaStreamSetTransactionSize(i2cp->tx.dma, txbytes); + + dmaStreamSetMode(i2cp->rx.dma, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->rx.dma, rxbuf); + dmaStreamSetTransactionSize(i2cp->rx.dma, rxbytes); + } +#endif +#else + i2cp->txptr = txbuf; + i2cp->rxptr = rxbuf; +#endif + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT)); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if ((dp->ISR & I2C_ISR_BUSY) == 0) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + /* Setting up the slave address.*/ + i2c_lld_set_address(i2cp, addr); + + /* Preparing the transfer.*/ + i2c_lld_setup_tx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling TX DMA.*/ + i2c_lld_start_tx_dma(i2cp); + + /* Transfer complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; +#else + /* Transfer complete and TX interrupts enabled.*/ + dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; +#endif + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + /* In case of a software timeout a STOP is sent as an extreme attempt + to release the bus and DMA is forcibly disabled.*/ + if (msg == MSG_TIMEOUT) { + dp->CR2 |= I2C_CR2_STOP; +#if STM32_I2C_USE_DMA == TRUE + i2c_lld_stop_rx_dma(i2cp); + i2c_lld_stop_tx_dma(i2cp); +#endif + } + + return msg; +} + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h b/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h index ee29a4e0c1..6d443d63f7 100644 --- a/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h +++ b/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h @@ -1,603 +1,603 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file I2Cv3/hal_i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef HAL_I2C_LLD_H -#define HAL_I2C_LLD_H - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name TIMINGR register definitions - * @{ - */ -#define STM32_TIMINGR_PRESC_MASK (15U << 28) -#define STM32_TIMINGR_PRESC(n) ((n) << 28) -#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) -#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) -#define STM32_TIMINGR_SDADEL_MASK (15U << 16) -#define STM32_TIMINGR_SDADEL(n) ((n) << 16) -#define STM32_TIMINGR_SCLH_MASK (255U << 8) -#define STM32_TIMINGR_SCLH(n) ((n) << 8) -#define STM32_TIMINGR_SCLL_MASK (255U << 0) -#define STM32_TIMINGR_SCLL(n) ((n) << 0) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C3 driver enable switch. - * @details If set to @p TRUE the support for I2C3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C3 FALSE -#endif - -/** - * @brief I2C4 driver enable switch. - * @details If set to @p TRUE the support for I2C4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C4 FALSE -#endif - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C3 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C4 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C4_IRQ_PRIORITY 10 -#endif - -/** - * @brief DMA use switch. - */ -#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) -#define STM32_I2C_USE_DMA TRUE -#endif - -/** - * @brief I2C1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C4_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Registry checks.*/ -#if !defined(STM32_HAS_I2C1) -#error "STM32_HAS_I2C1 not defined in registry" -#endif - -#if !defined(STM32_HAS_I2C2) -#error "STM32_HAS_I2C2 not defined in registry" -#endif - -#if !defined(STM32_HAS_I2C3) -#error "STM32_HAS_I2C3 not defined in registry" -#endif - -#if !defined(STM32_HAS_I2C4) -#error "STM32_HAS_I2C4 not defined in registry" -#endif - -#if !defined(STM32_I2C4_USE_BDMA) -#error "STM32_I2C4_USE_BDMA not defined in registry" -#endif - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 -#error "I2C3 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4 -#error "I2C4 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \ - !STM32_I2C_USE_I2C4 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C4" -#endif - -#if STM32_I2C_USE_DMA == TRUE - -#if STM32_I2C_USE_I2C1 -#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) -#error "STM32_I2C_I2C1_RX_DMA_STREAM not defined" -#endif - -#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) -#error "STM32_I2C_I2C1_TX_DMA_STREAM not defined" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C1 RX" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C1 TX" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C1" -#endif -#endif - -#if STM32_I2C_USE_I2C2 -#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) -#error "STM32_I2C_I2C2_RX_DMA_STREAM not defined" -#endif - -#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) -#error "STM32_I2C_I2C2_TX_DMA_STREAM not defined" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C2 RX" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C2 TX" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C2" -#endif -#endif - -#if STM32_I2C_USE_I2C3 -#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) -#error "STM32_I2C_I2C3_RX_DMA_STREAM not defined" -#endif - -#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) -#error "STM32_I2C_I2C3_TX_DMA_STREAM not defined" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C3 RX" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C3 TX" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C3" -#endif -#endif - -#if STM32_I2C_USE_I2C4 -#if STM32_I2C4_USE_BDMA - -#if !defined(STM32_I2C_I2C4_RX_BDMA_STREAM) -#error "STM32_I2C_I2C4_RX_BDMA_STREAM not defined" -#endif - -#if !defined(STM32_I2C_I2C4_TX_BDMA_STREAM) -#error "STM32_I2C_I2C4_TX_BDMA_STREAM not defined" -#endif - -#if !STM32_BDMA_IS_VALID_STREAM(STM32_I2C_I2C4_RX_BDMA_STREAM) -#error "Invalid BDMA stream assigned to I2C4 RX" -#endif - -#if !STM32_BDMA_IS_VALID_STREAM(STM32_I2C_I2C4_TX_BDMA_STREAM) -#error "Invalid BDMA stream assigned to I2C4 TX" -#endif - -#if !STM32_BDMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C4" -#endif - -#else /* !STM32_I2C4_USE_BDMA */ - -#if !defined(STM32_I2C_I2C4_RX_DMA_STREAM) -#error "STM32_I2C_I2C4_RX_DMA_STREAM not defined" -#endif - -#if !defined(STM32_I2C_I2C4_TX_DMA_STREAM) -#error "STM32_I2C_I2C4_TX_DMA_STREAM not defined" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C4_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C4 RX" -#endif - -#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C4_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to I2C4 TX" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C4" -#endif - -#endif /* !STM32_I2C4_USE_BDMA */ -#endif /* STM32_I2C_USE_I2C4 */ - -#if STM32_I2C4_USE_BDMA == TRUE - -#if STM32_I2C_USE_I2C1 || STM32_I2C_USE_I2C2 || STM32_I2C_USE_I2C3 -#define STM32_I2C_DMA_REQUIRED -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif -#endif - -#if STM32_I2C_USE_I2C4 -#define STM32_I2C_BDMA_REQUIRED -#if !defined(STM32_BDMA_REQUIRED) -#define STM32_BDMA_REQUIRED -#endif -#endif -#else /* STM32_I2C4_USE_BDMA != TRUE */ - -#if STM32_I2C_USE_I2C1 || STM32_I2C_USE_I2C2 || STM32_I2C_USE_I2C3 || STM32_I2C_USE_I2C4 -#define STM32_I2C_DMA_REQUIRED -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif -#endif - -#endif /* STM32_I2C4_USE_BDMA != TRUE */ - -#endif /* STM32_I2C_USE_DMA == TRUE */ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing an I2C address. - */ -typedef uint16_t i2caddr_t; - -/** - * @brief Type of I2C driver condition flags. - */ -typedef uint32_t i2cflags_t; - -/** - * @brief Type of I2C driver configuration structure. - */ -typedef struct { - /** - * @brief TIMINGR register initialization. - * @note Refer to the STM32 reference manual, the values are affected - * by the system clock settings in mcuconf.h. - */ - uint32_t timingr; - /** - * @brief CR1 register initialization. - * @note Leave to zero unless you know what you are doing. - */ - uint32_t cr1; - /** - * @brief CR2 register initialization. - * @note Only the ADD10 bit can eventually be specified here. - */ - uint32_t cr2; -} I2CConfig; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - mutex_t mutex; -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; - /** - * @brief Number of bytes in TX phase. - */ - size_t txbytes; - /** - * @brief Number of bytes in RX phase. - */ - size_t rxbytes; -#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; -#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_BDMA_REQUIRED) - /** - * @brief DMA type for this instance. - */ - bool is_bdma; -#endif - /** - * @brief Union of the RX DMA streams. - */ - union { -#if defined(STM32_I2C_DMA_REQUIRED) || defined(__DOXYGEN__) - /** - * @brief Receive DMA stream. - */ - const stm32_dma_stream_t *dma; -#endif -#if (STM32_I2C4_USE_BDMA == TRUE) || defined(__DOXYGEN__) -#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__) - /** - * @brief Receive BDMA stream. - */ - const stm32_bdma_stream_t *bdma; -#endif -#endif - } rx; - /** - * @brief Union of the TX DMA streams. - */ - union { -#if defined(STM32_I2C_DMA_REQUIRED) || defined(__DOXYGEN__) - /** - * @brief Transmit DMA stream. - */ - const stm32_dma_stream_t *dma; -#endif -#if (STM32_I2C4_USE_BDMA == TRUE) || defined(__DOXYGEN__) -#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__) - /** - * @brief Transmit DMA stream. - */ - const stm32_bdma_stream_t *bdma; -#endif -#endif - } tx; -#else /* STM32_I2C_USE_DMA == FALSE */ - /** - * @brief Pointer to the next TX buffer location. - */ - const uint8_t *txptr; - /** - * @brief Pointer to the next RX buffer location. - */ - uint8_t *rxptr; -#endif /* STM32_I2C_USE_DMA == FALSE */ - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#if STM32_I2C_USE_I2C3 -extern I2CDriver I2CD3; -#endif - -#if STM32_I2C_USE_I2C4 -extern I2CDriver I2CD4; -#endif - -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - sysinterval_t timeout); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* HAL_I2C_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file I2Cv3/hal_i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef HAL_I2C_LLD_H +#define HAL_I2C_LLD_H + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name TIMINGR register definitions + * @{ + */ +#define STM32_TIMINGR_PRESC_MASK (15U << 28) +#define STM32_TIMINGR_PRESC(n) ((n) << 28) +#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) +#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) +#define STM32_TIMINGR_SDADEL_MASK (15U << 16) +#define STM32_TIMINGR_SDADEL(n) ((n) << 16) +#define STM32_TIMINGR_SCLH_MASK (255U << 8) +#define STM32_TIMINGR_SCLH(n) ((n) << 8) +#define STM32_TIMINGR_SCLL_MASK (255U << 0) +#define STM32_TIMINGR_SCLL(n) ((n) << 0) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C3 FALSE +#endif + +/** + * @brief I2C4 driver enable switch. + * @details If set to @p TRUE the support for I2C4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C4 FALSE +#endif + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C4 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C4_IRQ_PRIORITY 10 +#endif + +/** + * @brief DMA use switch. + */ +#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) +#define STM32_I2C_USE_DMA TRUE +#endif + +/** + * @brief I2C1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C4_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks.*/ +#if !defined(STM32_HAS_I2C1) +#error "STM32_HAS_I2C1 not defined in registry" +#endif + +#if !defined(STM32_HAS_I2C2) +#error "STM32_HAS_I2C2 not defined in registry" +#endif + +#if !defined(STM32_HAS_I2C3) +#error "STM32_HAS_I2C3 not defined in registry" +#endif + +#if !defined(STM32_HAS_I2C4) +#error "STM32_HAS_I2C4 not defined in registry" +#endif + +#if !defined(STM32_I2C4_USE_BDMA) +#error "STM32_I2C4_USE_BDMA not defined in registry" +#endif + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4 +#error "I2C4 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \ + !STM32_I2C_USE_I2C4 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C4" +#endif + +#if STM32_I2C_USE_DMA == TRUE + +#if STM32_I2C_USE_I2C1 +#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) +#error "STM32_I2C_I2C1_RX_DMA_STREAM not defined" +#endif + +#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) +#error "STM32_I2C_I2C1_TX_DMA_STREAM not defined" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C1 RX" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C1 TX" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C1" +#endif +#endif + +#if STM32_I2C_USE_I2C2 +#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) +#error "STM32_I2C_I2C2_RX_DMA_STREAM not defined" +#endif + +#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) +#error "STM32_I2C_I2C2_TX_DMA_STREAM not defined" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C2 RX" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C2 TX" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C2" +#endif +#endif + +#if STM32_I2C_USE_I2C3 +#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) +#error "STM32_I2C_I2C3_RX_DMA_STREAM not defined" +#endif + +#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) +#error "STM32_I2C_I2C3_TX_DMA_STREAM not defined" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C3 RX" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C3 TX" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C3" +#endif +#endif + +#if STM32_I2C_USE_I2C4 +#if STM32_I2C4_USE_BDMA + +#if !defined(STM32_I2C_I2C4_RX_BDMA_STREAM) +#error "STM32_I2C_I2C4_RX_BDMA_STREAM not defined" +#endif + +#if !defined(STM32_I2C_I2C4_TX_BDMA_STREAM) +#error "STM32_I2C_I2C4_TX_BDMA_STREAM not defined" +#endif + +#if !STM32_BDMA_IS_VALID_STREAM(STM32_I2C_I2C4_RX_BDMA_STREAM) +#error "Invalid BDMA stream assigned to I2C4 RX" +#endif + +#if !STM32_BDMA_IS_VALID_STREAM(STM32_I2C_I2C4_TX_BDMA_STREAM) +#error "Invalid BDMA stream assigned to I2C4 TX" +#endif + +#if !STM32_BDMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C4" +#endif + +#else /* !STM32_I2C4_USE_BDMA */ + +#if !defined(STM32_I2C_I2C4_RX_DMA_STREAM) +#error "STM32_I2C_I2C4_RX_DMA_STREAM not defined" +#endif + +#if !defined(STM32_I2C_I2C4_TX_DMA_STREAM) +#error "STM32_I2C_I2C4_TX_DMA_STREAM not defined" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C4_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C4 RX" +#endif + +#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C4_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to I2C4 TX" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C4" +#endif + +#endif /* !STM32_I2C4_USE_BDMA */ +#endif /* STM32_I2C_USE_I2C4 */ + +#if STM32_I2C4_USE_BDMA == TRUE + +#if STM32_I2C_USE_I2C1 || STM32_I2C_USE_I2C2 || STM32_I2C_USE_I2C3 +#define STM32_I2C_DMA_REQUIRED +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif +#endif + +#if STM32_I2C_USE_I2C4 +#define STM32_I2C_BDMA_REQUIRED +#if !defined(STM32_BDMA_REQUIRED) +#define STM32_BDMA_REQUIRED +#endif +#endif +#else /* STM32_I2C4_USE_BDMA != TRUE */ + +#if STM32_I2C_USE_I2C1 || STM32_I2C_USE_I2C2 || STM32_I2C_USE_I2C3 || STM32_I2C_USE_I2C4 +#define STM32_I2C_DMA_REQUIRED +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif +#endif + +#endif /* STM32_I2C4_USE_BDMA != TRUE */ + +#endif /* STM32_I2C_USE_DMA == TRUE */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing an I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief Type of I2C driver condition flags. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief Type of I2C driver configuration structure. + */ +typedef struct { + /** + * @brief TIMINGR register initialization. + * @note Refer to the STM32 reference manual, the values are affected + * by the system clock settings in mcuconf.h. + */ + uint32_t timingr; + /** + * @brief CR1 register initialization. + * @note Leave to zero unless you know what you are doing. + */ + uint32_t cr1; + /** + * @brief CR2 register initialization. + * @note Only the ADD10 bit can eventually be specified here. + */ + uint32_t cr2; +} I2CConfig; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + /** + * @brief Number of bytes in TX phase. + */ + size_t txbytes; + /** + * @brief Number of bytes in RX phase. + */ + size_t rxbytes; +#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; +#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_BDMA_REQUIRED) + /** + * @brief DMA type for this instance. + */ + bool is_bdma; +#endif + /** + * @brief Union of the RX DMA streams. + */ + union { +#if defined(STM32_I2C_DMA_REQUIRED) || defined(__DOXYGEN__) + /** + * @brief Receive DMA stream. + */ + const stm32_dma_stream_t *dma; +#endif +#if (STM32_I2C4_USE_BDMA == TRUE) || defined(__DOXYGEN__) +#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__) + /** + * @brief Receive BDMA stream. + */ + const stm32_bdma_stream_t *bdma; +#endif +#endif + } rx; + /** + * @brief Union of the TX DMA streams. + */ + union { +#if defined(STM32_I2C_DMA_REQUIRED) || defined(__DOXYGEN__) + /** + * @brief Transmit DMA stream. + */ + const stm32_dma_stream_t *dma; +#endif +#if (STM32_I2C4_USE_BDMA == TRUE) || defined(__DOXYGEN__) +#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__) + /** + * @brief Transmit DMA stream. + */ + const stm32_bdma_stream_t *bdma; +#endif +#endif + } tx; +#else /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the next TX buffer location. + */ + const uint8_t *txptr; + /** + * @brief Pointer to the next RX buffer location. + */ + uint8_t *rxptr; +#endif /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#if STM32_I2C_USE_I2C3 +extern I2CDriver I2CD3; +#endif + +#if STM32_I2C_USE_I2C4 +extern I2CDriver I2CD4; +#endif + +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* HAL_I2C_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MACv1/driver.mk b/os/hal/ports/STM32/LLD/MACv1/driver.mk index 2964178c18..f0a8938e47 100644 --- a/os/hal/ports/STM32/LLD/MACv1/driver.mk +++ b/os/hal/ports/STM32/LLD/MACv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1 diff --git a/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c b/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c index 232fb0ec7e..907f509157 100644 --- a/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c +++ b/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c @@ -1,763 +1,763 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file MACv1/hal_mac_lld.c - * @brief STM32 low level MAC driver code. - * - * @addtogroup MAC - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -#include "hal_mii.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) - -/* Fixing inconsistencies in ST headers.*/ -#if !defined(ETH_MACMIIAR_CR_Div102) && defined(ETH_MACMIIAR_CR_DIV102) -#define ETH_MACMIIAR_CR_Div102 ETH_MACMIIAR_CR_DIV102 -#endif -#if !defined(ETH_MACMIIAR_CR_Div62) && defined(ETH_MACMIIAR_CR_DIV62) -#define ETH_MACMIIAR_CR_Div62 ETH_MACMIIAR_CR_DIV62 -#endif -#if !defined(ETH_MACMIIAR_CR_Div42) && defined(ETH_MACMIIAR_CR_DIV42) -#define ETH_MACMIIAR_CR_Div42 ETH_MACMIIAR_CR_DIV42 -#endif -#if !defined(ETH_MACMIIAR_CR_Div26) && defined(ETH_MACMIIAR_CR_DIV26) -#define ETH_MACMIIAR_CR_Div26 ETH_MACMIIAR_CR_DIV26 -#endif -#if !defined(ETH_MACMIIAR_CR_Div16) && defined(ETH_MACMIIAR_CR_DIV16) -#define ETH_MACMIIAR_CR_Div16 ETH_MACMIIAR_CR_DIV16 -#endif - -/* MII divider optimal value.*/ -#if (STM32_HCLK >= 150000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div102 -#elif (STM32_HCLK >= 100000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div62 -#elif (STM32_HCLK >= 60000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div42 -#elif (STM32_HCLK >= 35000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div26 -#elif (STM32_HCLK >= 20000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div16 -#else -#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief Ethernet driver 1. - */ -MACDriver ETHD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13, - 0x37, 0x01, 0x10}; - -static stm32_eth_rx_descriptor_t __eth_rd[STM32_MAC_RECEIVE_BUFFERS]; -static stm32_eth_tx_descriptor_t __eth_td[STM32_MAC_TRANSMIT_BUFFERS]; - -static uint32_t __eth_rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE]; -static uint32_t __eth_tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE]; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Writes a PHY register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] reg register number - * @param[in] value new register value - * - * @notapi - */ -void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) { - - ETH->MACMIIDR = value; - ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | - ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; - while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) - ; -} - -/** - * @brief Reads a PHY register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] reg register number - * - * @return The PHY register content. - * - * @notapi - */ -uint32_t mii_read(MACDriver *macp, uint32_t reg) { - - ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | ETH_MACMIIAR_MB; - while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) - ; - return ETH->MACMIIDR; -} - -#if !defined(BOARD_PHY_ADDRESS) -/** - * @brief PHY address detection. - * - * @param[in] macp pointer to the @p MACDriver object - */ -static void mii_find_phy(MACDriver *macp) { - uint32_t i; - -#if STM32_MAC_PHY_TIMEOUT > 0 - unsigned n = STM32_MAC_PHY_TIMEOUT; - do { -#endif - for (i = 0U; i <= 31U; i++) { - macp->phyaddr = i << 11U; - ETH->MACMIIDR = (i << 6U) | MACMIIDR_CR; - if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16U)) && - ((mii_read(macp, MII_PHYSID2) & 0xFFF0U) == (BOARD_PHY_ID & 0xFFF0U))) { - return; - } - } -#if STM32_MAC_PHY_TIMEOUT > 0 - n--; - } while (n > 0U); -#endif - /* Wrong or defective board.*/ - osalSysHalt("MAC failure"); -} -#endif - -/** - * @brief MAC address setup. - * - * @param[in] p pointer to a six bytes buffer containing the MAC - * address - */ -static void mac_lld_set_address(const uint8_t *p) { - - /* MAC address configuration, only a single address comparator is used, - hash table not used.*/ - ETH->MACA0HR = ((uint32_t)p[5] << 8) | - ((uint32_t)p[4] << 0); - ETH->MACA0LR = ((uint32_t)p[3] << 24) | - ((uint32_t)p[2] << 16) | - ((uint32_t)p[1] << 8) | - ((uint32_t)p[0] << 0); - ETH->MACA1HR = 0x0000FFFF; - ETH->MACA1LR = 0xFFFFFFFF; - ETH->MACA2HR = 0x0000FFFF; - ETH->MACA2LR = 0xFFFFFFFF; - ETH->MACA3HR = 0x0000FFFF; - ETH->MACA3LR = 0xFFFFFFFF; - ETH->MACHTHR = 0; - ETH->MACHTLR = 0; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -OSAL_IRQ_HANDLER(STM32_ETH_HANDLER) { - uint32_t dmasr; - - OSAL_IRQ_PROLOGUE(); - - dmasr = ETH->DMASR; - ETH->DMASR = dmasr; /* Clear status bits.*/ - - if (dmasr & ETH_DMASR_RS) { - /* Data Received.*/ - osalSysLockFromISR(); - osalThreadDequeueAllI(ÐD1.rdqueue, MSG_RESET); -#if MAC_USE_EVENTS - osalEventBroadcastFlagsI(ÐD1.rdevent, 0); -#endif - osalSysUnlockFromISR(); - } - - if (dmasr & ETH_DMASR_TS) { - /* Data Transmitted.*/ - osalSysLockFromISR(); - osalThreadDequeueAllI(ÐD1.tdqueue, MSG_RESET); - osalSysUnlockFromISR(); - } - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level MAC initialization. - * - * @notapi - */ -void mac_lld_init(void) { - unsigned i; - - macObjectInit(ÐD1); - ETHD1.link_up = false; - - /* Descriptor tables are initialized in chained mode, note that the first - word is not initialized here but in mac_lld_start().*/ - for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) { - __eth_rd[i].rdes1 = STM32_RDES1_RCH | STM32_MAC_BUFFERS_SIZE; - __eth_rd[i].rdes2 = (uint32_t)__eth_rb[i]; - __eth_rd[i].rdes3 = (uint32_t)&__eth_rd[(i + 1) % STM32_MAC_RECEIVE_BUFFERS]; - } - for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) { - __eth_td[i].tdes1 = 0; - __eth_td[i].tdes2 = (uint32_t)__eth_tb[i]; - __eth_td[i].tdes3 = (uint32_t)&__eth_td[(i + 1) % STM32_MAC_TRANSMIT_BUFFERS]; - } - - /* Selection of the RMII or MII mode based on info exported by board.h.*/ -#if defined(STM32F10X_CL) -#if defined(BOARD_PHY_RMII) - AFIO->MAPR |= AFIO_MAPR_MII_RMII_SEL; -#else - AFIO->MAPR &= ~AFIO_MAPR_MII_RMII_SEL; -#endif -#elif defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F7XX) -#if defined(BOARD_PHY_RMII) - SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; -#else - SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; -#endif -#else -#error "unsupported STM32 platform for MAC driver" -#endif - - /* Reset of the MAC core.*/ - rccResetETH(); - - /* MAC clocks temporary activation.*/ - rccEnableETH(true); - - /* PHY address setup.*/ -#if defined(BOARD_PHY_ADDRESS) - ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11; -#else - mii_find_phy(ÐD1); -#endif - -#if defined(BOARD_PHY_RESET) - /* PHY board-specific reset procedure.*/ - BOARD_PHY_RESET(); -#else - /* PHY soft reset procedure.*/ - mii_write(ÐD1, MII_BMCR, BMCR_RESET); -#if defined(BOARD_PHY_RESET_DELAY) - osalSysPolledDelayX(BOARD_PHY_RESET_DELAY); -#endif - while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) - ; -#endif - -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power down mode until the driver will be started.*/ - mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); -#endif - - /* MAC clocks stopped again.*/ - rccDisableETH(); -} - -/** - * @brief Configures and activates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @notapi - */ -void mac_lld_start(MACDriver *macp) { - unsigned i; - - /* Resets the state of all descriptors.*/ - for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) - __eth_rd[i].rdes0 = STM32_RDES0_OWN; - macp->rxptr = (stm32_eth_rx_descriptor_t *)__eth_rd; - for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) - __eth_td[i].tdes0 = STM32_TDES0_TCH; - macp->txptr = (stm32_eth_tx_descriptor_t *)__eth_td; - - /* MAC clocks activation and commanded reset procedure.*/ - rccEnableETH(true); -#if defined(STM32_MAC_DMABMR_SR) - ETH->DMABMR |= ETH_DMABMR_SR; - while (ETH->DMABMR & ETH_DMABMR_SR) - ; -#endif - - /* ISR vector enabled.*/ - nvicEnableVector(STM32_ETH_NUMBER, STM32_MAC_ETH1_IRQ_PRIORITY); - -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power up mode.*/ - mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); -#endif - - /* MAC configuration.*/ - ETH->MACFFR = 0; - ETH->MACFCR = 0; - ETH->MACVLANTR = 0; - - /* MAC address setup.*/ - if (macp->config->mac_address == NULL) - mac_lld_set_address(default_mac_address); - else - mac_lld_set_address(macp->config->mac_address); - - /* Transmitter and receiver enabled. - Note that the complete setup of the MAC is performed when the link - status is detected.*/ -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - ETH->MACCR = ETH_MACCR_IPCO | ETH_MACCR_RE | ETH_MACCR_TE; -#else - ETH->MACCR = ETH_MACCR_RE | ETH_MACCR_TE; -#endif - - /* MMC configuration: - Disable all MMC interrupts.*/ - ETH->MMCRIMR = ETH_MMCRIMR_RFCEM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RGUFM; - ETH->MMCTIMR = ETH_MMCTIMR_TGFSCM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFM; - - /* DMA configuration: - Descriptor chains pointers.*/ - ETH->DMARDLAR = (uint32_t)__eth_rd; - ETH->DMATDLAR = (uint32_t)__eth_td; - - /* Enabling required interrupt sources.*/ - ETH->DMASR = ETH->DMASR; - ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; - - /* DMA general settings.*/ - ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_RDP_1Beat | ETH_DMABMR_PBL_1Beat; - - /* Check because errata on some devices. There should be no need to - disable flushing because the TXFIFO should be empty on macStart().*/ -#if !defined(STM32_MAC_DISABLE_TX_FLUSH) - /* Transmit FIFO flush.*/ - ETH->DMAOMR = ETH_DMAOMR_FTF; - while (ETH->DMAOMR & ETH_DMAOMR_FTF) - ; -#endif - - /* DMA final configuration and start.*/ - ETH->DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_TSF | - ETH_DMAOMR_ST | ETH_DMAOMR_SR; -} - -/** - * @brief Deactivates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @notapi - */ -void mac_lld_stop(MACDriver *macp) { - - if (macp->state != MAC_STOP) { -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power down mode until the driver will be restarted.*/ - mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); -#endif - - /* MAC and DMA stopped.*/ - ETH->MACCR = 0; - ETH->DMAOMR = 0; - ETH->DMAIER = 0; - ETH->DMASR = ETH->DMASR; - - /* MAC clocks stopped.*/ - rccDisableETH(); - - /* ISR vector disabled.*/ - nvicDisableVector(STM32_ETH_NUMBER); - } -} - -/** - * @brief Returns a transmission descriptor. - * @details One of the available transmission descriptors is locked and - * returned. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] tdp pointer to a @p MACTransmitDescriptor structure - * @return The operation status. - * @retval MSG_OK the descriptor has been obtained. - * @retval MSG_TIMEOUT descriptor not available. - * - * @notapi - */ -msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp) { - stm32_eth_tx_descriptor_t *tdes; - - if (!macp->link_up) - return MSG_TIMEOUT; - - /* Get Current TX descriptor.*/ - tdes = macp->txptr; - - /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by - another thread.*/ - if (tdes->tdes0 & (STM32_TDES0_OWN | STM32_TDES0_LOCKED)) { - return MSG_TIMEOUT; - } - - /* Marks the current descriptor as locked using a reserved bit.*/ - tdes->tdes0 |= STM32_TDES0_LOCKED; - - /* Next TX descriptor to use.*/ - macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3; - - /* Set the buffer size and configuration.*/ - tdp->offset = 0; - tdp->size = STM32_MAC_BUFFERS_SIZE; - tdp->physdesc = tdes; - - return MSG_OK; -} - -/** - * @brief Releases a transmit descriptor and starts the transmission of the - * enqueued data as a single frame. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * - * @notapi - */ -void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { - - osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "attempt to release descriptor already owned by DMA"); - - osalSysLock(); - - /* Unlocks the descriptor and returns it to the DMA engine.*/ - tdp->physdesc->tdes1 = tdp->offset; - tdp->physdesc->tdes0 = STM32_TDES0_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) | - STM32_TDES0_IC | STM32_TDES0_LS | STM32_TDES0_FS | - STM32_TDES0_TCH | STM32_TDES0_OWN; - - /* Wait for the write to tdes0 to go through before resuming the DMA.*/ - __DSB(); - - /* If the DMA engine is stalled then a restart request is issued.*/ - if ((ETH->DMASR & ETH_DMASR_TPS) == ETH_DMASR_TPS_Suspended) { - ETH->DMASR = ETH_DMASR_TBUS; - ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/ - } - - osalSysUnlock(); -} - -/** - * @brief Returns a receive descriptor. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] rdp pointer to a @p MACReceiveDescriptor structure - * @return The operation status. - * @retval MSG_OK the descriptor has been obtained. - * @retval MSG_TIMEOUT descriptor not available. - * - * @notapi - */ -msg_t mac_lld_get_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp) { - stm32_eth_rx_descriptor_t *rdes; - - /* Get Current RX descriptor.*/ - rdes = macp->rxptr; - - /* Iterates through received frames until a valid one is found, invalid - frames are discarded.*/ - while (!(rdes->rdes0 & STM32_RDES0_OWN)) { - if (!(rdes->rdes0 & (STM32_RDES0_AFM | STM32_RDES0_ES)) -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - && (rdes->rdes0 & STM32_RDES0_FT) - && !(rdes->rdes0 & (STM32_RDES0_IPHCE | STM32_RDES0_PCE)) -#endif - && (rdes->rdes0 & STM32_RDES0_FS) && (rdes->rdes0 & STM32_RDES0_LS)) { - /* Found a valid one.*/ - rdp->offset = 0; - rdp->size = ((rdes->rdes0 & STM32_RDES0_FL_MASK) >> 16) - 4; - rdp->physdesc = rdes; - macp->rxptr = (stm32_eth_rx_descriptor_t *)rdes->rdes3; - - return MSG_OK; - } - /* Invalid frame found, purging.*/ - rdes->rdes0 = STM32_RDES0_OWN; - rdes = (stm32_eth_rx_descriptor_t *)rdes->rdes3; - } - - /* Next descriptor to check.*/ - macp->rxptr = rdes; - - return MSG_TIMEOUT; -} - -/** - * @brief Releases a receive descriptor. - * @details The descriptor and its buffer are made available for more incoming - * frames. - * - * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure - * - * @notapi - */ -void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { - - osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "attempt to release descriptor already owned by DMA"); - - osalSysLock(); - - /* Give buffer back to the Ethernet DMA.*/ - rdp->physdesc->rdes0 = STM32_RDES0_OWN; - - /* Wait for the write to rdes0 to go through before resuming the DMA.*/ - __DSB(); - - /* If the DMA engine is stalled then a restart request is issued.*/ - if ((ETH->DMASR & ETH_DMASR_RPS) == ETH_DMASR_RPS_Suspended) { - ETH->DMASR = ETH_DMASR_RBUS; - ETH->DMARPDR = ETH_DMASR_RBUS; /* Any value is OK.*/ - } - - osalSysUnlock(); -} - -/** - * @brief Updates and returns the link status. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The link status. - * @retval true if the link is active. - * @retval false if the link is down. - * - * @notapi - */ -bool mac_lld_poll_link_status(MACDriver *macp) { - uint32_t maccr, bmsr, bmcr; - - maccr = ETH->MACCR; - - /* PHY CR and SR registers read.*/ - (void)mii_read(macp, MII_BMSR); - bmsr = mii_read(macp, MII_BMSR); - bmcr = mii_read(macp, MII_BMCR); - - /* Check on auto-negotiation mode.*/ - if (bmcr & BMCR_ANENABLE) { - uint32_t lpa; - - /* Auto-negotiation must be finished without faults and link established.*/ - if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) != - (BMSR_LSTATUS | BMSR_ANEGCOMPLETE)) - return macp->link_up = false; - - /* Auto-negotiation enabled, checks the LPA register.*/ - lpa = mii_read(macp, MII_LPA); - - /* Check on link speed.*/ - if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) - maccr |= ETH_MACCR_FES; - else - maccr &= ~ETH_MACCR_FES; - - /* Check on link mode.*/ - if (lpa & (LPA_10FULL | LPA_100FULL)) - maccr |= ETH_MACCR_DM; - else - maccr &= ~ETH_MACCR_DM; - } - else { - /* Link must be established.*/ - if (!(bmsr & BMSR_LSTATUS)) - return macp->link_up = false; - - /* Check on link speed.*/ - if (bmcr & BMCR_SPEED100) - maccr |= ETH_MACCR_FES; - else - maccr &= ~ETH_MACCR_FES; - - /* Check on link mode.*/ - if (bmcr & BMCR_FULLDPLX) - maccr |= ETH_MACCR_DM; - else - maccr &= ~ETH_MACCR_DM; - } - - /* Changes the mode in the MAC.*/ - ETH->MACCR = maccr; - - /* Returns the link status.*/ - return macp->link_up = true; -} - -/** - * @brief Writes to a transmit descriptor's stream. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] buf pointer to the buffer containing the data to be - * written - * @param[in] size number of bytes to be written - * @return The number of bytes written into the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if the maximum - * frame size is reached. - * - * @notapi - */ -size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size) { - - osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "attempt to write descriptor already owned by DMA"); - - if (size > tdp->size - tdp->offset) - size = tdp->size - tdp->offset; - - if (size > 0) { - memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); - tdp->offset += size; - } - return size; -} - -/** - * @brief Reads from a receive descriptor's stream. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] buf pointer to the buffer that will receive the read data - * @param[in] size number of bytes to be read - * @return The number of bytes read from the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if there are - * no more bytes to read. - * - * @notapi - */ -size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size) { - - osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "attempt to read descriptor already owned by DMA"); - - if (size > rdp->size - rdp->offset) - size = rdp->size - rdp->offset; - - if (size > 0) { - memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size); - rdp->offset += size; - } - return size; -} - -#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) -/** - * @brief Returns a pointer to the next transmit buffer in the descriptor - * chain. - * @note The API guarantees that enough buffers can be requested to fill - * a whole frame. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] size size of the requested buffer. Specify the frame size - * on the first call then scale the value down subtracting - * the amount of data already copied into the previous - * buffers. - * @param[out] sizep pointer to variable receiving the buffer size, it is - * zero when the last buffer has already been returned. - * Note that a returned size lower than the amount - * requested means that more buffers must be requested - * in order to fill the frame data entirely. - * @return Pointer to the returned buffer. - * @retval NULL if the buffer chain has been entirely scanned. - * - * @notapi - */ -uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, - size_t size, - size_t *sizep) { - - if (tdp->offset == 0) { - *sizep = tdp->size; - tdp->offset = size; - return (uint8_t *)tdp->physdesc->tdes2; - } - *sizep = 0; - return NULL; -} - -/** - * @brief Returns a pointer to the next receive buffer in the descriptor - * chain. - * @note The API guarantees that the descriptor chain contains a whole - * frame. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[out] sizep pointer to variable receiving the buffer size, it is - * zero when the last buffer has already been returned. - * @return Pointer to the returned buffer. - * @retval NULL if the buffer chain has been entirely scanned. - * - * @notapi - */ -const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, - size_t *sizep) { - - if (rdp->size > 0) { - *sizep = rdp->size; - rdp->offset = rdp->size; - rdp->size = 0; - return (uint8_t *)rdp->physdesc->rdes2; - } - *sizep = 0; - return NULL; -} -#endif /* MAC_USE_ZERO_COPY */ - -#endif /* HAL_USE_MAC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file MACv1/hal_mac_lld.c + * @brief STM32 low level MAC driver code. + * + * @addtogroup MAC + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +#include "hal_mii.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) + +/* Fixing inconsistencies in ST headers.*/ +#if !defined(ETH_MACMIIAR_CR_Div102) && defined(ETH_MACMIIAR_CR_DIV102) +#define ETH_MACMIIAR_CR_Div102 ETH_MACMIIAR_CR_DIV102 +#endif +#if !defined(ETH_MACMIIAR_CR_Div62) && defined(ETH_MACMIIAR_CR_DIV62) +#define ETH_MACMIIAR_CR_Div62 ETH_MACMIIAR_CR_DIV62 +#endif +#if !defined(ETH_MACMIIAR_CR_Div42) && defined(ETH_MACMIIAR_CR_DIV42) +#define ETH_MACMIIAR_CR_Div42 ETH_MACMIIAR_CR_DIV42 +#endif +#if !defined(ETH_MACMIIAR_CR_Div26) && defined(ETH_MACMIIAR_CR_DIV26) +#define ETH_MACMIIAR_CR_Div26 ETH_MACMIIAR_CR_DIV26 +#endif +#if !defined(ETH_MACMIIAR_CR_Div16) && defined(ETH_MACMIIAR_CR_DIV16) +#define ETH_MACMIIAR_CR_Div16 ETH_MACMIIAR_CR_DIV16 +#endif + +/* MII divider optimal value.*/ +#if (STM32_HCLK >= 150000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div102 +#elif (STM32_HCLK >= 100000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div62 +#elif (STM32_HCLK >= 60000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div42 +#elif (STM32_HCLK >= 35000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div26 +#elif (STM32_HCLK >= 20000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div16 +#else +#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief Ethernet driver 1. + */ +MACDriver ETHD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13, + 0x37, 0x01, 0x10}; + +static stm32_eth_rx_descriptor_t __eth_rd[STM32_MAC_RECEIVE_BUFFERS]; +static stm32_eth_tx_descriptor_t __eth_td[STM32_MAC_TRANSMIT_BUFFERS]; + +static uint32_t __eth_rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE]; +static uint32_t __eth_tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Writes a PHY register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] reg register number + * @param[in] value new register value + * + * @notapi + */ +void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) { + + ETH->MACMIIDR = value; + ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | + ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; + while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) + ; +} + +/** + * @brief Reads a PHY register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] reg register number + * + * @return The PHY register content. + * + * @notapi + */ +uint32_t mii_read(MACDriver *macp, uint32_t reg) { + + ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | ETH_MACMIIAR_MB; + while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) + ; + return ETH->MACMIIDR; +} + +#if !defined(BOARD_PHY_ADDRESS) +/** + * @brief PHY address detection. + * + * @param[in] macp pointer to the @p MACDriver object + */ +static void mii_find_phy(MACDriver *macp) { + uint32_t i; + +#if STM32_MAC_PHY_TIMEOUT > 0 + unsigned n = STM32_MAC_PHY_TIMEOUT; + do { +#endif + for (i = 0U; i <= 31U; i++) { + macp->phyaddr = i << 11U; + ETH->MACMIIDR = (i << 6U) | MACMIIDR_CR; + if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16U)) && + ((mii_read(macp, MII_PHYSID2) & 0xFFF0U) == (BOARD_PHY_ID & 0xFFF0U))) { + return; + } + } +#if STM32_MAC_PHY_TIMEOUT > 0 + n--; + } while (n > 0U); +#endif + /* Wrong or defective board.*/ + osalSysHalt("MAC failure"); +} +#endif + +/** + * @brief MAC address setup. + * + * @param[in] p pointer to a six bytes buffer containing the MAC + * address + */ +static void mac_lld_set_address(const uint8_t *p) { + + /* MAC address configuration, only a single address comparator is used, + hash table not used.*/ + ETH->MACA0HR = ((uint32_t)p[5] << 8) | + ((uint32_t)p[4] << 0); + ETH->MACA0LR = ((uint32_t)p[3] << 24) | + ((uint32_t)p[2] << 16) | + ((uint32_t)p[1] << 8) | + ((uint32_t)p[0] << 0); + ETH->MACA1HR = 0x0000FFFF; + ETH->MACA1LR = 0xFFFFFFFF; + ETH->MACA2HR = 0x0000FFFF; + ETH->MACA2LR = 0xFFFFFFFF; + ETH->MACA3HR = 0x0000FFFF; + ETH->MACA3LR = 0xFFFFFFFF; + ETH->MACHTHR = 0; + ETH->MACHTLR = 0; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +OSAL_IRQ_HANDLER(STM32_ETH_HANDLER) { + uint32_t dmasr; + + OSAL_IRQ_PROLOGUE(); + + dmasr = ETH->DMASR; + ETH->DMASR = dmasr; /* Clear status bits.*/ + + if (dmasr & ETH_DMASR_RS) { + /* Data Received.*/ + osalSysLockFromISR(); + osalThreadDequeueAllI(ÐD1.rdqueue, MSG_RESET); +#if MAC_USE_EVENTS + osalEventBroadcastFlagsI(ÐD1.rdevent, 0); +#endif + osalSysUnlockFromISR(); + } + + if (dmasr & ETH_DMASR_TS) { + /* Data Transmitted.*/ + osalSysLockFromISR(); + osalThreadDequeueAllI(ÐD1.tdqueue, MSG_RESET); + osalSysUnlockFromISR(); + } + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level MAC initialization. + * + * @notapi + */ +void mac_lld_init(void) { + unsigned i; + + macObjectInit(ÐD1); + ETHD1.link_up = false; + + /* Descriptor tables are initialized in chained mode, note that the first + word is not initialized here but in mac_lld_start().*/ + for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) { + __eth_rd[i].rdes1 = STM32_RDES1_RCH | STM32_MAC_BUFFERS_SIZE; + __eth_rd[i].rdes2 = (uint32_t)__eth_rb[i]; + __eth_rd[i].rdes3 = (uint32_t)&__eth_rd[(i + 1) % STM32_MAC_RECEIVE_BUFFERS]; + } + for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) { + __eth_td[i].tdes1 = 0; + __eth_td[i].tdes2 = (uint32_t)__eth_tb[i]; + __eth_td[i].tdes3 = (uint32_t)&__eth_td[(i + 1) % STM32_MAC_TRANSMIT_BUFFERS]; + } + + /* Selection of the RMII or MII mode based on info exported by board.h.*/ +#if defined(STM32F10X_CL) +#if defined(BOARD_PHY_RMII) + AFIO->MAPR |= AFIO_MAPR_MII_RMII_SEL; +#else + AFIO->MAPR &= ~AFIO_MAPR_MII_RMII_SEL; +#endif +#elif defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F7XX) +#if defined(BOARD_PHY_RMII) + SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; +#else + SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; +#endif +#else +#error "unsupported STM32 platform for MAC driver" +#endif + + /* Reset of the MAC core.*/ + rccResetETH(); + + /* MAC clocks temporary activation.*/ + rccEnableETH(true); + + /* PHY address setup.*/ +#if defined(BOARD_PHY_ADDRESS) + ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11; +#else + mii_find_phy(ÐD1); +#endif + +#if defined(BOARD_PHY_RESET) + /* PHY board-specific reset procedure.*/ + BOARD_PHY_RESET(); +#else + /* PHY soft reset procedure.*/ + mii_write(ÐD1, MII_BMCR, BMCR_RESET); +#if defined(BOARD_PHY_RESET_DELAY) + osalSysPolledDelayX(BOARD_PHY_RESET_DELAY); +#endif + while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) + ; +#endif + +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power down mode until the driver will be started.*/ + mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); +#endif + + /* MAC clocks stopped again.*/ + rccDisableETH(); +} + +/** + * @brief Configures and activates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @notapi + */ +void mac_lld_start(MACDriver *macp) { + unsigned i; + + /* Resets the state of all descriptors.*/ + for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) + __eth_rd[i].rdes0 = STM32_RDES0_OWN; + macp->rxptr = (stm32_eth_rx_descriptor_t *)__eth_rd; + for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) + __eth_td[i].tdes0 = STM32_TDES0_TCH; + macp->txptr = (stm32_eth_tx_descriptor_t *)__eth_td; + + /* MAC clocks activation and commanded reset procedure.*/ + rccEnableETH(true); +#if defined(STM32_MAC_DMABMR_SR) + ETH->DMABMR |= ETH_DMABMR_SR; + while (ETH->DMABMR & ETH_DMABMR_SR) + ; +#endif + + /* ISR vector enabled.*/ + nvicEnableVector(STM32_ETH_NUMBER, STM32_MAC_ETH1_IRQ_PRIORITY); + +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power up mode.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); +#endif + + /* MAC configuration.*/ + ETH->MACFFR = 0; + ETH->MACFCR = 0; + ETH->MACVLANTR = 0; + + /* MAC address setup.*/ + if (macp->config->mac_address == NULL) + mac_lld_set_address(default_mac_address); + else + mac_lld_set_address(macp->config->mac_address); + + /* Transmitter and receiver enabled. + Note that the complete setup of the MAC is performed when the link + status is detected.*/ +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + ETH->MACCR = ETH_MACCR_IPCO | ETH_MACCR_RE | ETH_MACCR_TE; +#else + ETH->MACCR = ETH_MACCR_RE | ETH_MACCR_TE; +#endif + + /* MMC configuration: + Disable all MMC interrupts.*/ + ETH->MMCRIMR = ETH_MMCRIMR_RFCEM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RGUFM; + ETH->MMCTIMR = ETH_MMCTIMR_TGFSCM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFM; + + /* DMA configuration: + Descriptor chains pointers.*/ + ETH->DMARDLAR = (uint32_t)__eth_rd; + ETH->DMATDLAR = (uint32_t)__eth_td; + + /* Enabling required interrupt sources.*/ + ETH->DMASR = ETH->DMASR; + ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; + + /* DMA general settings.*/ + ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_RDP_1Beat | ETH_DMABMR_PBL_1Beat; + + /* Check because errata on some devices. There should be no need to + disable flushing because the TXFIFO should be empty on macStart().*/ +#if !defined(STM32_MAC_DISABLE_TX_FLUSH) + /* Transmit FIFO flush.*/ + ETH->DMAOMR = ETH_DMAOMR_FTF; + while (ETH->DMAOMR & ETH_DMAOMR_FTF) + ; +#endif + + /* DMA final configuration and start.*/ + ETH->DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_TSF | + ETH_DMAOMR_ST | ETH_DMAOMR_SR; +} + +/** + * @brief Deactivates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @notapi + */ +void mac_lld_stop(MACDriver *macp) { + + if (macp->state != MAC_STOP) { +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power down mode until the driver will be restarted.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); +#endif + + /* MAC and DMA stopped.*/ + ETH->MACCR = 0; + ETH->DMAOMR = 0; + ETH->DMAIER = 0; + ETH->DMASR = ETH->DMASR; + + /* MAC clocks stopped.*/ + rccDisableETH(); + + /* ISR vector disabled.*/ + nvicDisableVector(STM32_ETH_NUMBER); + } +} + +/** + * @brief Returns a transmission descriptor. + * @details One of the available transmission descriptors is locked and + * returned. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @return The operation status. + * @retval MSG_OK the descriptor has been obtained. + * @retval MSG_TIMEOUT descriptor not available. + * + * @notapi + */ +msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp) { + stm32_eth_tx_descriptor_t *tdes; + + if (!macp->link_up) + return MSG_TIMEOUT; + + /* Get Current TX descriptor.*/ + tdes = macp->txptr; + + /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by + another thread.*/ + if (tdes->tdes0 & (STM32_TDES0_OWN | STM32_TDES0_LOCKED)) { + return MSG_TIMEOUT; + } + + /* Marks the current descriptor as locked using a reserved bit.*/ + tdes->tdes0 |= STM32_TDES0_LOCKED; + + /* Next TX descriptor to use.*/ + macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3; + + /* Set the buffer size and configuration.*/ + tdp->offset = 0; + tdp->size = STM32_MAC_BUFFERS_SIZE; + tdp->physdesc = tdes; + + return MSG_OK; +} + +/** + * @brief Releases a transmit descriptor and starts the transmission of the + * enqueued data as a single frame. + * + * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure + * + * @notapi + */ +void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { + + osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "attempt to release descriptor already owned by DMA"); + + osalSysLock(); + + /* Unlocks the descriptor and returns it to the DMA engine.*/ + tdp->physdesc->tdes1 = tdp->offset; + tdp->physdesc->tdes0 = STM32_TDES0_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) | + STM32_TDES0_IC | STM32_TDES0_LS | STM32_TDES0_FS | + STM32_TDES0_TCH | STM32_TDES0_OWN; + + /* Wait for the write to tdes0 to go through before resuming the DMA.*/ + __DSB(); + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMASR & ETH_DMASR_TPS) == ETH_DMASR_TPS_Suspended) { + ETH->DMASR = ETH_DMASR_TBUS; + ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/ + } + + osalSysUnlock(); +} + +/** + * @brief Returns a receive descriptor. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @return The operation status. + * @retval MSG_OK the descriptor has been obtained. + * @retval MSG_TIMEOUT descriptor not available. + * + * @notapi + */ +msg_t mac_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp) { + stm32_eth_rx_descriptor_t *rdes; + + /* Get Current RX descriptor.*/ + rdes = macp->rxptr; + + /* Iterates through received frames until a valid one is found, invalid + frames are discarded.*/ + while (!(rdes->rdes0 & STM32_RDES0_OWN)) { + if (!(rdes->rdes0 & (STM32_RDES0_AFM | STM32_RDES0_ES)) +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + && (rdes->rdes0 & STM32_RDES0_FT) + && !(rdes->rdes0 & (STM32_RDES0_IPHCE | STM32_RDES0_PCE)) +#endif + && (rdes->rdes0 & STM32_RDES0_FS) && (rdes->rdes0 & STM32_RDES0_LS)) { + /* Found a valid one.*/ + rdp->offset = 0; + rdp->size = ((rdes->rdes0 & STM32_RDES0_FL_MASK) >> 16) - 4; + rdp->physdesc = rdes; + macp->rxptr = (stm32_eth_rx_descriptor_t *)rdes->rdes3; + + return MSG_OK; + } + /* Invalid frame found, purging.*/ + rdes->rdes0 = STM32_RDES0_OWN; + rdes = (stm32_eth_rx_descriptor_t *)rdes->rdes3; + } + + /* Next descriptor to check.*/ + macp->rxptr = rdes; + + return MSG_TIMEOUT; +} + +/** + * @brief Releases a receive descriptor. + * @details The descriptor and its buffer are made available for more incoming + * frames. + * + * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure + * + * @notapi + */ +void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { + + osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), + "attempt to release descriptor already owned by DMA"); + + osalSysLock(); + + /* Give buffer back to the Ethernet DMA.*/ + rdp->physdesc->rdes0 = STM32_RDES0_OWN; + + /* Wait for the write to rdes0 to go through before resuming the DMA.*/ + __DSB(); + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMASR & ETH_DMASR_RPS) == ETH_DMASR_RPS_Suspended) { + ETH->DMASR = ETH_DMASR_RBUS; + ETH->DMARPDR = ETH_DMASR_RBUS; /* Any value is OK.*/ + } + + osalSysUnlock(); +} + +/** + * @brief Updates and returns the link status. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The link status. + * @retval true if the link is active. + * @retval false if the link is down. + * + * @notapi + */ +bool mac_lld_poll_link_status(MACDriver *macp) { + uint32_t maccr, bmsr, bmcr; + + maccr = ETH->MACCR; + + /* PHY CR and SR registers read.*/ + (void)mii_read(macp, MII_BMSR); + bmsr = mii_read(macp, MII_BMSR); + bmcr = mii_read(macp, MII_BMCR); + + /* Check on auto-negotiation mode.*/ + if (bmcr & BMCR_ANENABLE) { + uint32_t lpa; + + /* Auto-negotiation must be finished without faults and link established.*/ + if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) != + (BMSR_LSTATUS | BMSR_ANEGCOMPLETE)) + return macp->link_up = false; + + /* Auto-negotiation enabled, checks the LPA register.*/ + lpa = mii_read(macp, MII_LPA); + + /* Check on link speed.*/ + if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) + maccr |= ETH_MACCR_FES; + else + maccr &= ~ETH_MACCR_FES; + + /* Check on link mode.*/ + if (lpa & (LPA_10FULL | LPA_100FULL)) + maccr |= ETH_MACCR_DM; + else + maccr &= ~ETH_MACCR_DM; + } + else { + /* Link must be established.*/ + if (!(bmsr & BMSR_LSTATUS)) + return macp->link_up = false; + + /* Check on link speed.*/ + if (bmcr & BMCR_SPEED100) + maccr |= ETH_MACCR_FES; + else + maccr &= ~ETH_MACCR_FES; + + /* Check on link mode.*/ + if (bmcr & BMCR_FULLDPLX) + maccr |= ETH_MACCR_DM; + else + maccr &= ~ETH_MACCR_DM; + } + + /* Changes the mode in the MAC.*/ + ETH->MACCR = maccr; + + /* Returns the link status.*/ + return macp->link_up = true; +} + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be + * written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if the maximum + * frame size is reached. + * + * @notapi + */ +size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size) { + + osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "attempt to write descriptor already owned by DMA"); + + if (size > tdp->size - tdp->offset) + size = tdp->size - tdp->offset; + + if (size > 0) { + memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); + tdp->offset += size; + } + return size; +} + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if there are + * no more bytes to read. + * + * @notapi + */ +size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size) { + + osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), + "attempt to read descriptor already owned by DMA"); + + if (size > rdp->size - rdp->offset) + size = rdp->size - rdp->offset; + + if (size > 0) { + memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size); + rdp->offset += size; + } + return size; +} + +#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) +/** + * @brief Returns a pointer to the next transmit buffer in the descriptor + * chain. + * @note The API guarantees that enough buffers can be requested to fill + * a whole frame. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] size size of the requested buffer. Specify the frame size + * on the first call then scale the value down subtracting + * the amount of data already copied into the previous + * buffers. + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * Note that a returned size lower than the amount + * requested means that more buffers must be requested + * in order to fill the frame data entirely. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @notapi + */ +uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, + size_t size, + size_t *sizep) { + + if (tdp->offset == 0) { + *sizep = tdp->size; + tdp->offset = size; + return (uint8_t *)tdp->physdesc->tdes2; + } + *sizep = 0; + return NULL; +} + +/** + * @brief Returns a pointer to the next receive buffer in the descriptor + * chain. + * @note The API guarantees that the descriptor chain contains a whole + * frame. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @notapi + */ +const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, + size_t *sizep) { + + if (rdp->size > 0) { + *sizep = rdp->size; + rdp->offset = rdp->size; + rdp->size = 0; + return (uint8_t *)rdp->physdesc->rdes2; + } + *sizep = 0; + return NULL; +} +#endif /* MAC_USE_ZERO_COPY */ + +#endif /* HAL_USE_MAC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h b/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h index 31ad0164b0..4df08efe41 100644 --- a/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h +++ b/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h @@ -1,359 +1,359 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file MACv1/hal_mac_lld.h - * @brief STM32 low level MAC driver header. - * - * @addtogroup MAC - * @{ - */ - -#ifndef HAL_MAC_LLD_H -#define HAL_MAC_LLD_H - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief This implementation supports the zero-copy mode API. - */ -#define MAC_SUPPORTS_ZERO_COPY TRUE - -/** - * @name RDES0 constants - * @{ - */ -#define STM32_RDES0_OWN 0x80000000 -#define STM32_RDES0_AFM 0x40000000 -#define STM32_RDES0_FL_MASK 0x3FFF0000 -#define STM32_RDES0_ES 0x00008000 -#define STM32_RDES0_DESERR 0x00004000 -#define STM32_RDES0_SAF 0x00002000 -#define STM32_RDES0_LE 0x00001000 -#define STM32_RDES0_OE 0x00000800 -#define STM32_RDES0_VLAN 0x00000400 -#define STM32_RDES0_FS 0x00000200 -#define STM32_RDES0_LS 0x00000100 -#define STM32_RDES0_IPHCE 0x00000080 -#define STM32_RDES0_LCO 0x00000040 -#define STM32_RDES0_FT 0x00000020 -#define STM32_RDES0_RWT 0x00000010 -#define STM32_RDES0_RE 0x00000008 -#define STM32_RDES0_DE 0x00000004 -#define STM32_RDES0_CE 0x00000002 -#define STM32_RDES0_PCE 0x00000001 -/** @} */ - -/** - * @name RDES1 constants - * @{ - */ -#define STM32_RDES1_DIC 0x80000000 -#define STM32_RDES1_RBS2_MASK 0x1FFF0000 -#define STM32_RDES1_RER 0x00008000 -#define STM32_RDES1_RCH 0x00004000 -#define STM32_RDES1_RBS1_MASK 0x00001FFF -/** @} */ - -/** - * @name TDES0 constants - * @{ - */ -#define STM32_TDES0_OWN 0x80000000 -#define STM32_TDES0_IC 0x40000000 -#define STM32_TDES0_LS 0x20000000 -#define STM32_TDES0_FS 0x10000000 -#define STM32_TDES0_DC 0x08000000 -#define STM32_TDES0_DP 0x04000000 -#define STM32_TDES0_TTSE 0x02000000 -#define STM32_TDES0_LOCKED 0x01000000 /* NOTE: Pseudo flag. */ -#define STM32_TDES0_CIC_MASK 0x00C00000 -#define STM32_TDES0_CIC(n) ((n) << 22) -#define STM32_TDES0_TER 0x00200000 -#define STM32_TDES0_TCH 0x00100000 -#define STM32_TDES0_TTSS 0x00020000 -#define STM32_TDES0_IHE 0x00010000 -#define STM32_TDES0_ES 0x00008000 -#define STM32_TDES0_JT 0x00004000 -#define STM32_TDES0_FF 0x00002000 -#define STM32_TDES0_IPE 0x00001000 -#define STM32_TDES0_LCA 0x00000800 -#define STM32_TDES0_NC 0x00000400 -#define STM32_TDES0_LCO 0x00000200 -#define STM32_TDES0_EC 0x00000100 -#define STM32_TDES0_VF 0x00000080 -#define STM32_TDES0_CC_MASK 0x00000078 -#define STM32_TDES0_ED 0x00000004 -#define STM32_TDES0_UF 0x00000002 -#define STM32_TDES0_DB 0x00000001 -/** @} */ - -/** - * @name TDES1 constants - * @{ - */ -#define STM32_TDES1_TBS2_MASK 0x1FFF0000 -#define STM32_TDES1_TBS1_MASK 0x00001FFF -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Number of available transmit buffers. - */ -#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) -#define STM32_MAC_TRANSMIT_BUFFERS 2 -#endif - -/** - * @brief Number of available receive buffers. - */ -#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) -#define STM32_MAC_RECEIVE_BUFFERS 4 -#endif - -/** - * @brief Maximum supported frame size. - */ -#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define STM32_MAC_BUFFERS_SIZE 1522 -#endif - -/** - * @brief PHY detection timeout. - * @details Timeout for PHY address detection, the scan for a PHY is performed - * the specified number of times before invoking the failure handler. - * This setting applies only if the PHY address is not explicitly - * set in the board header file using @p BOARD_PHY_ADDRESS. A zero - * value disables the timeout and a single search is performed. - */ -#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_MAC_PHY_TIMEOUT 100 -#endif - -/** - * @brief Change the PHY power state inside the driver. - */ -#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__) -#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE -#endif - -/** - * @brief ETHD1 interrupt priority level setting. - */ -#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_MAC_ETH1_IRQ_PRIORITY 13 -#endif - -/** - * @brief IP checksum offload. - * @details The following modes are available: - * - 0 Function disabled. - * - 1 Only IP header checksum calculation and insertion are enabled. - * - 2 IP header checksum and payload checksum calculation and - * insertion are enabled, but pseudo-header checksum is not - * calculated in hardware. - * - 3 IP Header checksum and payload checksum calculation and - * insertion are enabled, and pseudo-header checksum is - * calculated in hardware. - * . - */ -#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__) -#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an STM32 Ethernet receive descriptor. - */ -typedef struct { - volatile uint32_t rdes0; - volatile uint32_t rdes1; - volatile uint32_t rdes2; - volatile uint32_t rdes3; -} stm32_eth_rx_descriptor_t; - -/** - * @brief Type of an STM32 Ethernet transmit descriptor. - */ -typedef struct { - volatile uint32_t tdes0; - volatile uint32_t tdes1; - volatile uint32_t tdes2; - volatile uint32_t tdes3; -} stm32_eth_tx_descriptor_t; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief MAC address. - */ - uint8_t *mac_address; - /* End of the mandatory fields.*/ -} MACConfig; - -/** - * @brief Structure representing a MAC driver. - */ -struct MACDriver { - /** - * @brief Driver state. - */ - macstate_t state; - /** - * @brief Current configuration data. - */ - const MACConfig *config; - /** - * @brief Transmit semaphore. - */ - threads_queue_t tdqueue; - /** - * @brief Receive semaphore. - */ - threads_queue_t rdqueue; -#if MAC_USE_EVENTS || defined(__DOXYGEN__) - /** - * @brief Receive event. - */ - event_source_t rdevent; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Link status flag. - */ - bool link_up; - /** - * @brief PHY address (pre shifted). - */ - uint32_t phyaddr; - /** - * @brief Receive next frame pointer. - */ - stm32_eth_rx_descriptor_t *rxptr; - /** - * @brief Transmit next frame pointer. - */ - stm32_eth_tx_descriptor_t *txptr; -}; - -/** - * @brief Structure representing a transmit descriptor. - */ -typedef struct { - /** - * @brief Current write offset. - */ - size_t offset; - /** - * @brief Available space size. - */ - size_t size; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the physical descriptor. - */ - stm32_eth_tx_descriptor_t *physdesc; -} MACTransmitDescriptor; - -/** - * @brief Structure representing a receive descriptor. - */ -typedef struct { - /** - * @brief Current read offset. - */ - size_t offset; - /** - * @brief Available data size. - */ - size_t size; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the physical descriptor. - */ - stm32_eth_rx_descriptor_t *physdesc; -} MACReceiveDescriptor; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern MACDriver ETHD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void mii_write(MACDriver *macp, uint32_t reg, uint32_t value); - uint32_t mii_read(MACDriver *macp, uint32_t reg); - void mac_lld_init(void); - void mac_lld_start(MACDriver *macp); - void mac_lld_stop(MACDriver *macp); - msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp); - void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); - msg_t mac_lld_get_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp); - void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); - bool mac_lld_poll_link_status(MACDriver *macp); - size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size); - size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size); -#if MAC_USE_ZERO_COPY - uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, - size_t size, - size_t *sizep); - const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, - size_t *sizep); -#endif /* MAC_USE_ZERO_COPY */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_MAC */ - -#endif /* HAL_MAC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file MACv1/hal_mac_lld.h + * @brief STM32 low level MAC driver header. + * + * @addtogroup MAC + * @{ + */ + +#ifndef HAL_MAC_LLD_H +#define HAL_MAC_LLD_H + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief This implementation supports the zero-copy mode API. + */ +#define MAC_SUPPORTS_ZERO_COPY TRUE + +/** + * @name RDES0 constants + * @{ + */ +#define STM32_RDES0_OWN 0x80000000 +#define STM32_RDES0_AFM 0x40000000 +#define STM32_RDES0_FL_MASK 0x3FFF0000 +#define STM32_RDES0_ES 0x00008000 +#define STM32_RDES0_DESERR 0x00004000 +#define STM32_RDES0_SAF 0x00002000 +#define STM32_RDES0_LE 0x00001000 +#define STM32_RDES0_OE 0x00000800 +#define STM32_RDES0_VLAN 0x00000400 +#define STM32_RDES0_FS 0x00000200 +#define STM32_RDES0_LS 0x00000100 +#define STM32_RDES0_IPHCE 0x00000080 +#define STM32_RDES0_LCO 0x00000040 +#define STM32_RDES0_FT 0x00000020 +#define STM32_RDES0_RWT 0x00000010 +#define STM32_RDES0_RE 0x00000008 +#define STM32_RDES0_DE 0x00000004 +#define STM32_RDES0_CE 0x00000002 +#define STM32_RDES0_PCE 0x00000001 +/** @} */ + +/** + * @name RDES1 constants + * @{ + */ +#define STM32_RDES1_DIC 0x80000000 +#define STM32_RDES1_RBS2_MASK 0x1FFF0000 +#define STM32_RDES1_RER 0x00008000 +#define STM32_RDES1_RCH 0x00004000 +#define STM32_RDES1_RBS1_MASK 0x00001FFF +/** @} */ + +/** + * @name TDES0 constants + * @{ + */ +#define STM32_TDES0_OWN 0x80000000 +#define STM32_TDES0_IC 0x40000000 +#define STM32_TDES0_LS 0x20000000 +#define STM32_TDES0_FS 0x10000000 +#define STM32_TDES0_DC 0x08000000 +#define STM32_TDES0_DP 0x04000000 +#define STM32_TDES0_TTSE 0x02000000 +#define STM32_TDES0_LOCKED 0x01000000 /* NOTE: Pseudo flag. */ +#define STM32_TDES0_CIC_MASK 0x00C00000 +#define STM32_TDES0_CIC(n) ((n) << 22) +#define STM32_TDES0_TER 0x00200000 +#define STM32_TDES0_TCH 0x00100000 +#define STM32_TDES0_TTSS 0x00020000 +#define STM32_TDES0_IHE 0x00010000 +#define STM32_TDES0_ES 0x00008000 +#define STM32_TDES0_JT 0x00004000 +#define STM32_TDES0_FF 0x00002000 +#define STM32_TDES0_IPE 0x00001000 +#define STM32_TDES0_LCA 0x00000800 +#define STM32_TDES0_NC 0x00000400 +#define STM32_TDES0_LCO 0x00000200 +#define STM32_TDES0_EC 0x00000100 +#define STM32_TDES0_VF 0x00000080 +#define STM32_TDES0_CC_MASK 0x00000078 +#define STM32_TDES0_ED 0x00000004 +#define STM32_TDES0_UF 0x00000002 +#define STM32_TDES0_DB 0x00000001 +/** @} */ + +/** + * @name TDES1 constants + * @{ + */ +#define STM32_TDES1_TBS2_MASK 0x1FFF0000 +#define STM32_TDES1_TBS1_MASK 0x00001FFF +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Number of available transmit buffers. + */ +#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#endif + +/** + * @brief Number of available receive buffers. + */ +#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) +#define STM32_MAC_RECEIVE_BUFFERS 4 +#endif + +/** + * @brief Maximum supported frame size. + */ +#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define STM32_MAC_BUFFERS_SIZE 1522 +#endif + +/** + * @brief PHY detection timeout. + * @details Timeout for PHY address detection, the scan for a PHY is performed + * the specified number of times before invoking the failure handler. + * This setting applies only if the PHY address is not explicitly + * set in the board header file using @p BOARD_PHY_ADDRESS. A zero + * value disables the timeout and a single search is performed. + */ +#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_MAC_PHY_TIMEOUT 100 +#endif + +/** + * @brief Change the PHY power state inside the driver. + */ +#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__) +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#endif + +/** + * @brief ETHD1 interrupt priority level setting. + */ +#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#endif + +/** + * @brief IP checksum offload. + * @details The following modes are available: + * - 0 Function disabled. + * - 1 Only IP header checksum calculation and insertion are enabled. + * - 2 IP header checksum and payload checksum calculation and + * insertion are enabled, but pseudo-header checksum is not + * calculated in hardware. + * - 3 IP Header checksum and payload checksum calculation and + * insertion are enabled, and pseudo-header checksum is + * calculated in hardware. + * . + */ +#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__) +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an STM32 Ethernet receive descriptor. + */ +typedef struct { + volatile uint32_t rdes0; + volatile uint32_t rdes1; + volatile uint32_t rdes2; + volatile uint32_t rdes3; +} stm32_eth_rx_descriptor_t; + +/** + * @brief Type of an STM32 Ethernet transmit descriptor. + */ +typedef struct { + volatile uint32_t tdes0; + volatile uint32_t tdes1; + volatile uint32_t tdes2; + volatile uint32_t tdes3; +} stm32_eth_tx_descriptor_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief MAC address. + */ + uint8_t *mac_address; + /* End of the mandatory fields.*/ +} MACConfig; + +/** + * @brief Structure representing a MAC driver. + */ +struct MACDriver { + /** + * @brief Driver state. + */ + macstate_t state; + /** + * @brief Current configuration data. + */ + const MACConfig *config; + /** + * @brief Transmit semaphore. + */ + threads_queue_t tdqueue; + /** + * @brief Receive semaphore. + */ + threads_queue_t rdqueue; +#if MAC_USE_EVENTS || defined(__DOXYGEN__) + /** + * @brief Receive event. + */ + event_source_t rdevent; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Link status flag. + */ + bool link_up; + /** + * @brief PHY address (pre shifted). + */ + uint32_t phyaddr; + /** + * @brief Receive next frame pointer. + */ + stm32_eth_rx_descriptor_t *rxptr; + /** + * @brief Transmit next frame pointer. + */ + stm32_eth_tx_descriptor_t *txptr; +}; + +/** + * @brief Structure representing a transmit descriptor. + */ +typedef struct { + /** + * @brief Current write offset. + */ + size_t offset; + /** + * @brief Available space size. + */ + size_t size; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_tx_descriptor_t *physdesc; +} MACTransmitDescriptor; + +/** + * @brief Structure representing a receive descriptor. + */ +typedef struct { + /** + * @brief Current read offset. + */ + size_t offset; + /** + * @brief Available data size. + */ + size_t size; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_rx_descriptor_t *physdesc; +} MACReceiveDescriptor; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern MACDriver ETHD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void mii_write(MACDriver *macp, uint32_t reg, uint32_t value); + uint32_t mii_read(MACDriver *macp, uint32_t reg); + void mac_lld_init(void); + void mac_lld_start(MACDriver *macp); + void mac_lld_stop(MACDriver *macp); + msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp); + void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); + msg_t mac_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp); + void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); + bool mac_lld_poll_link_status(MACDriver *macp); + size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size); + size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size); +#if MAC_USE_ZERO_COPY + uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, + size_t size, + size_t *sizep); + const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, + size_t *sizep); +#endif /* MAC_USE_ZERO_COPY */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_MAC */ + +#endif /* HAL_MAC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MACv2/driver.mk b/os/hal/ports/STM32/LLD/MACv2/driver.mk index e746dc14b0..c9fc45f13f 100644 --- a/os/hal/ports/STM32/LLD/MACv2/driver.mk +++ b/os/hal/ports/STM32/LLD/MACv2/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2 diff --git a/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c b/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c index 1987973c1f..b02303ba10 100644 --- a/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c +++ b/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.c @@ -1,773 +1,773 @@ -/* - ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file MACv2/hal_mac_lld.c - * @brief STM32 low level MAC driver code. - * - * @addtogroup MAC - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -#include "hal_mii.h" - -/* Fixes for errors in ST headers.*/ -#if ETH_DMADSR_RPS_FETCHING_Pos == 12 -#undef ETH_DMADSR_RPS_FETCHING_Pos -#define ETH_DMADSR_RPS_FETCHING_Pos (8U) -#endif - -#if ETH_DMADSR_RPS_WAITING_Pos == 12 -#undef ETH_DMADSR_RPS_WAITING_Pos -#define ETH_DMADSR_RPS_WAITING_Pos (9U) -#endif - -#if ETH_DMADSR_RPS_SUSPENDED_Pos == 14 -#undef ETH_DMADSR_RPS_SUSPENDED_Pos -#define ETH_DMADSR_RPS_SUSPENDED_Pos (10U) -#endif - -#if ETH_DMADSR_RPS_CLOSING_Pos == 12 -#undef ETH_DMADSR_RPS_CLOSING_Pos -#define ETH_DMADSR_RPS_CLOSING_Pos (10U) -#endif - -#if ETH_DMADSR_RPS_TIMESTAMP_WR_Pos == 13 -#undef ETH_DMADSR_RPS_TIMESTAMP_WR_Pos -#undef ETH_DMADSR_RPS_TIMESTAMP_WR_Msk -#define ETH_DMADSR_RPS_TIMESTAMP_WR_Pos (10U) -#define ETH_DMADSR_RPS_TIMESTAMP_WR_Msk (0x6UL << ETH_DMADSR_RPS_TIMESTAMP_WR_Pos) -#endif - -#if ETH_DMADSR_RPS_TRANSFERRING_Pos == 12 -#undef ETH_DMADSR_RPS_TRANSFERRING_Pos -#define ETH_DMADSR_RPS_TRANSFERRING_Pos (10U) -#endif - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) - -/* Fixing inconsistencies in ST headers.*/ -#if !defined(ETH_MACMDIOAR_CR_Div124) && defined(ETH_MACMDIOAR_CR_DIV124) -#define ETH_MACMDIOAR_CR_Div124 ETH_MACMDIOAR_CR_DIV124 -#endif -#if !defined(ETH_MACMDIOAR_CR_Div102) && defined(ETH_MACMDIOAR_CR_DIV102) -#define ETH_MACMDIOAR_CR_Div102 ETH_MACMDIOAR_CR_DIV102 -#endif -#if !defined(ETH_MACMDIOAR_CR_Div62) && defined(ETH_MACMDIOAR_CR_DIV62) -#define ETH_MACMDIOAR_CR_Div62 ETH_MACMDIOAR_CR_DIV62 -#endif -#if !defined(ETH_MACMDIOAR_CR_Div42) && defined(ETH_MACMDIOAR_CR_DIV42) -#define ETH_MACMDIOAR_CR_Div42 ETH_MACMDIOAR_CR_DIV42 -#endif -#if !defined(ETH_MACMDIOAR_CR_Div26) && defined(ETH_MACMDIOAR_CR_DIV26) -#define ETH_MACMDIOAR_CR_Div26 ETH_MACMDIOAR_CR_DIV26 -#endif -#if !defined(ETH_MACMDIOAR_CR_Div16) && defined(ETH_MACMDIOAR_CR_DIV16) -#define ETH_MACMDIOAR_CR_Div16 ETH_MACMDIOAR_CR_DIV16 -#endif - -/* MII divider optimal value.*/ -#if (STM32_HCLK > 300000000) -#error "STM32_HCLK above maximum frequency for ETH operations (300MHz)" -#elif (STM32_HCLK >= 250000000) -#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div124 -#elif (STM32_HCLK >= 150000000) -#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div102 -#elif (STM32_HCLK >= 100000000) -#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div62 -#elif (STM32_HCLK >= 60000000) -#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div42 -#elif (STM32_HCLK >= 35000000) -#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div26 -#elif (STM32_HCLK >= 20000000) -#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div16 -#else -#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief Ethernet driver 1. - */ -MACDriver ETHD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13, - 0x37, 0x01, 0x10}; - -static stm32_eth_rx_descriptor_t __eth_rd[STM32_MAC_RECEIVE_BUFFERS] - __attribute__((aligned(4), __section__(".eth"))); -static stm32_eth_tx_descriptor_t __eth_td[STM32_MAC_TRANSMIT_BUFFERS] - __attribute__((aligned(4), __section__(".eth"))); - -static uint32_t __eth_rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE] - __attribute__((aligned(4), __section__(".eth"))); -static uint32_t __eth_tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE] - __attribute__((aligned(4), __section__(".eth"))); - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Writes a PHY register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] reg register number - * @param[in] value new register value - * - * @notapi - */ -void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) { - - ETH->MACMDIODR = value; - ETH->MACMDIOAR = macp->phyaddr | (reg << ETH_MACMDIOAR_RDA_Pos) | MACMDIODR_CR | - ETH_MACMDIOAR_MOC_WR | ETH_MACMDIOAR_MB; - while ((ETH->MACMDIOAR & ETH_MACMDIOAR_MB) != 0) - ; -} - -/** - * @brief Reads a PHY register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] reg register number - * - * @return The PHY register content. - * - * @notapi - */ -uint32_t mii_read(MACDriver *macp, uint32_t reg) { - - ETH->MACMDIOAR = macp->phyaddr | (reg << ETH_MACMDIOAR_RDA_Pos) | MACMDIODR_CR | - ETH_MACMDIOAR_MOC_RD | ETH_MACMDIOAR_MB; - while ((ETH->MACMDIOAR & ETH_MACMDIOAR_MB) != 0) - ; - return ETH->MACMDIODR; -} - -#if !defined(BOARD_PHY_ADDRESS) -/** - * @brief PHY address detection. - * - * @param[in] macp pointer to the @p MACDriver object - */ -static void mii_find_phy(MACDriver *macp) { - uint32_t i; - -#if STM32_MAC_PHY_TIMEOUT > 0 - unsigned n = STM32_MAC_PHY_TIMEOUT; - do { -#endif - for (i = 0U; i <= 31U; i++) { - macp->phyaddr = i << ETH_MACMDIOAR_PA_Pos; - ETH->MACMDIOAR = (i << ETH_MACMDIOAR_RDA_Pos) | MACMDIODR_CR; - ETH->MACMDIODR = (i << ETH_MACMDIODR_RA_Pos) | MACMDIODR_CR; - if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16U)) && - ((mii_read(macp, MII_PHYSID2) & 0xFFF0U) == (BOARD_PHY_ID & 0xFFF0U))) { - return; - } - } -#if STM32_MAC_PHY_TIMEOUT > 0 - n--; - } while (n > 0U); -#endif - /* Wrong or defective board.*/ - osalSysHalt("MAC failure"); -} -#endif - -/** - * @brief MAC address setup. - * - * @param[in] p pointer to a six bytes buffer containing the MAC - * address - */ -static void mac_lld_set_address(const uint8_t *p) { - - /* MAC address configuration, only a single address comparator is used, - hash table not used.*/ - ETH->MACA0HR = ((uint32_t)p[5] << 8) | - ((uint32_t)p[4] << 0); - ETH->MACA0LR = ((uint32_t)p[3] << 24) | - ((uint32_t)p[2] << 16) | - ((uint32_t)p[1] << 8) | - ((uint32_t)p[0] << 0); - ETH->MACA1HR = 0; - ETH->MACA1LR = 0; - ETH->MACA2HR = 0; - ETH->MACA2LR = 0; - ETH->MACA3HR = 0; - ETH->MACA3LR = 0; - ETH->MACHT0R = 0; - ETH->MACHT1R = 0; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -OSAL_IRQ_HANDLER(STM32_ETH_HANDLER) { - uint32_t dmasr; - - OSAL_IRQ_PROLOGUE(); - - dmasr = ETH->DMACSR; - - if (dmasr & ETH_DMACSR_RI) { - /* Data Received.*/ - ETH->DMACSR = ETH_DMACSR_RI; - ETH->DMACIER &= ~ETH_DMACIER_RIE; - osalSysLockFromISR(); - osalThreadDequeueAllI(ÐD1.rdqueue, MSG_RESET); -#if MAC_USE_EVENTS - osalEventBroadcastFlagsI(ÐD1.rdevent, 0); -#endif - osalSysUnlockFromISR(); - } - - if (dmasr & ETH_DMACSR_TI) { - /* Data Transmitted.*/ - ETH->DMACSR = ETH_DMACSR_TI; - osalSysLockFromISR(); - osalThreadDequeueAllI(ÐD1.tdqueue, MSG_RESET); - osalSysUnlockFromISR(); - } - - ETH->DMACSR |= ETH_DMACSR_NIS; - ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE; - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level MAC initialization. - * - * @notapi - */ -void mac_lld_init(void) { - unsigned i,j; - - macObjectInit(ÐD1); - ETHD1.link_up = false; - - /* Descriptor tables are initialized in ring mode, note that the first - word is not initialized here but in mac_lld_start().*/ - for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) { - __eth_rd[i].rdes0 = (uint32_t)__eth_rb[i]; - __eth_rd[i].rdes1 = 0; - __eth_rd[i].rdes2 = 0; - __eth_rd[i].rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; - for (j = 0; j < BUFFER_SIZE; j++) { - __eth_rb[i][j] = 825373492; /* telltale "1234" */ - } - } - for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) { - __eth_td[i].tdes0 = 0; - __eth_td[i].tdes1 = 0; - __eth_td[i].tdes2 = 0; - __eth_td[i].tdes3 = 0; - for (j = 0; j < BUFFER_SIZE; j++) { - __eth_tb[i][j] = 892745528; /* telltale "5678" */ - } - } - - /* Selection of the RMII or MII mode based on info exported by board.h.*/ -#if defined(STM32H7XX) - SYSCFG->PMCR |= SYSCFG_PMCR_PA1SO; -#if defined(BOARD_PHY_RMII) - SYSCFG->PMCR |= SYSCFG_PMCR_EPIS_SEL_2; - SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_1; - SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_0; -#else - SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_2; - SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_1; - SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_0; -#endif -#else -#error "unsupported STM32 platform for MACv2 driver" -#endif - - /* Reset of the MAC core.*/ - rccResetETH(); - - /* MAC clocks temporary activation.*/ - rccEnableETH(true); - - /* PHY address setup.*/ -#if defined(BOARD_PHY_ADDRESS) - ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11; -#else - mii_find_phy(ÐD1); -#endif - -#if defined(BOARD_PHY_RESET) - /* PHY board-specific reset procedure.*/ - BOARD_PHY_RESET(); -#else - /* PHY soft reset procedure.*/ - mii_write(ÐD1, MII_BMCR, BMCR_RESET); -#if defined(BOARD_PHY_RESET_DELAY) - osalSysPolledDelayX(BOARD_PHY_RESET_DELAY); -#endif - while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) - ; -#endif - -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power down mode until the driver will be started.*/ - mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); -#endif - - /* MAC clocks stopped again.*/ - rccDisableETH(); -} - -/** - * @brief Configures and activates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @notapi - */ -void mac_lld_start(MACDriver *macp) { - unsigned i; - - /* Resets the state of all descriptors.*/ - for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) - __eth_rd[i].rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; - macp->rdindex = 0; - for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) - __eth_td[i].tdes3 = 0; - macp->tdindex = 0; - - /* MAC clocks activation and commanded reset procedure.*/ - rccEnableETH(true); - - /* ISR vector enabled.*/ - nvicEnableVector(STM32_ETH_NUMBER, STM32_MAC_ETH1_IRQ_PRIORITY); - -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power up mode.*/ - mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); -#endif - - ETH->DMAMR |= ETH_DMAMR_SWR; - while (ETH->DMAMR & ETH_DMAMR_SWR) - ; - - /* MAC configuration.*/ - ETH->MACCR = ETH_MACCR_DO; - ETH->MACPFR = 0; - ETH->MACTFCR = 0; - ETH->MACRFCR = 0; - ETH->MACVTR = 0; - - /* MAC address setup.*/ - if (macp->config->mac_address == NULL) - mac_lld_set_address(default_mac_address); - else - mac_lld_set_address(macp->config->mac_address); - - /* Transmitter and receiver enabled. - Note that the complete setup of the MAC is performed when the link - status is detected.*/ -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - ETH->MACCR |= ETH_MACCR_IPC | ETH_MACCR_RE | ETH_MACCR_TE; -#else - ETH->MACCR |= ETH_MACCR_RE | ETH_MACCR_TE; -#endif - - /* DMA general settings.*/ - ETH->DMASBMR = ETH_DMASBMR_AAL; - ETH->DMACCR = ETH_DMACCR_DSL_0BIT; - ETH->DMAMR = ETH_DMAMR_INTM_0 | ETH_DMAMR_PR_8_1 | ETH_DMAMR_TXPR; /* TX:RX 8:1 */ - /* DMA configuration: - Descriptor rings pointers.*/ - ETH->DMACTDLAR = (uint32_t)&__eth_td[0]; - ETH->DMACTDRLR = STM32_MAC_TRANSMIT_BUFFERS-1; - ETH->DMACRDLAR = (uint32_t)&__eth_rd[0]; - ETH->DMACRDRLR = STM32_MAC_RECEIVE_BUFFERS-1; - - /* Enabling required interrupt sources.*/ - ETH->DMACSR = ETH_DMACSR_NIS; - ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE; - - - /* Check because errata on some devices. There should be no need to - disable flushing because the TXFIFO should be empty on macStart().*/ -#if !defined(STM32_MAC_DISABLE_TX_FLUSH) - /* Transmit FIFO flush.*/ - ETH->MTLTQOMR = ETH_MTLTQOMR_FTQ; - while (ETH->MTLTQOMR & ETH_MTLTQOMR_FTQ) - ; -#endif - - /* DMA final configuration and start.*/ - ETH->MTLRQOMR = ETH_MTLRQOMR_DISTCPEF | ETH_MTLRQOMR_RSF; - ETH->MTLTQOMR = ETH_MTLTQOMR_TSF; - ETH->DMACTCR = ETH_DMACTCR_ST | ETH_DMACTCR_TPBL_1PBL; - ETH->DMACRCR = ETH_DMACRCR_SR | ETH_DMACRCR_RPBL_1PBL - | (STM32_MAC_BUFFERS_SIZE << ETH_DMACRCR_RBSZ_Pos - & ETH_DMACRCR_RBSZ); -} - -/** - * @brief Deactivates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @notapi - */ -void mac_lld_stop(MACDriver *macp) { - - if (macp->state != MAC_STOP) { -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power down mode until the driver will be restarted.*/ - mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); -#endif - - /* MAC and DMA stopped.*/ - ETH->MACCR = 0; - ETH->MTLRQOMR = 0; - ETH->DMACIER = 0; - ETH->DMACSR = ETH->DMACSR; - - /* MAC clocks stopped.*/ - rccDisableETH(); - - /* ISR vector disabled.*/ - nvicDisableVector(STM32_ETH_NUMBER); - } -} - -/** - * @brief Returns a transmission descriptor. - * @details One of the available transmission descriptors is locked and - * returned. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] tdp pointer to a @p MACTransmitDescriptor structure - * @return The operation status. - * @retval MSG_OK the descriptor has been obtained. - * @retval MSG_TIMEOUT descriptor not available. - * - * @notapi - */ -msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp) { - stm32_eth_tx_descriptor_t *tdes; - - if (!macp->link_up) - return MSG_TIMEOUT; - - /* Get Current TX descriptor.*/ - tdes = (stm32_eth_tx_descriptor_t *)&__eth_td[macp->tdindex]; - - /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by - another thread.*/ - if ((tdes->tdes3 & (STM32_TDES3_OWN)) | (tdes->tdes1 > 0)) { - return MSG_TIMEOUT; - } - - tdes->tdes0 = (uint32_t )__eth_tb[macp->tdindex]; - /* Marks the current descriptor as locked using a reserved bit.*/ - /*tdes->tdes0 |= STM32_TDES0_LOCKED; */ - tdes->tdes1++; - - /* Next TX descriptor to use.*/ - macp->tdindex++; - if (macp->tdindex >= STM32_MAC_TRANSMIT_BUFFERS) - macp->tdindex = 0; - - /* Set the buffer size and configuration.*/ - tdp->offset = 0; - tdp->size = STM32_MAC_BUFFERS_SIZE; - tdp->physdesc = tdes; - - return MSG_OK; -} - -/** - * @brief Releases a transmit descriptor and starts the transmission of the - * enqueued data as a single frame. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * - * @notapi - */ -void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { - - osalDbgAssert(!(tdp->physdesc->tdes3 & STM32_TDES3_OWN), - "attempt to release descriptor already owned by DMA"); - - osalSysLock(); - - /* Unlocks the descriptor and returns it to the DMA engine.*/ - tdp->physdesc->tdes1 = 0; - tdp->physdesc->tdes2 = STM32_TDES2_IOC | (tdp->offset & STM32_TDES2_B1L_MASK); -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - tdp->physdesc->tdes3 = STM32_TDES3_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) | - STM32_TDES3_LD | STM32_TDES3_FD | - STM32_TDES3_OWN; -#else - tdp->physdesc->tdes3 = STM32_TDES3_LD | STM32_TDES3_FD | - STM32_TDES3_OWN; -#endif - - /* Wait for the write to tdes3 to go through before resuming the DMA.*/ - __DSB(); - - /* If the DMA engine is stalled then a restart request is issued.*/ - if ((ETH->DMADSR & ETH_DMADSR_TPS) == ETH_DMADSR_TPS_SUSPENDED) { - ETH->DMACSR = ETH_DMACSR_TBU; - } - ETH->DMACTDTPR = 0; - - osalSysUnlock(); -} - -/** - * @brief Returns a receive descriptor. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] rdp pointer to a @p MACReceiveDescriptor structure - * @return The operation status. - * @retval MSG_OK the descriptor has been obtained. - * @retval MSG_TIMEOUT descriptor not available. - * - * @notapi - */ -msg_t mac_lld_get_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp) { - stm32_eth_rx_descriptor_t *rdes; - - /* Get Current RX descriptor.*/ - rdes = (stm32_eth_rx_descriptor_t *)&__eth_rd[macp->rdindex]; - - /* Iterates through received frames until a valid one is found, invalid - frames are discarded.*/ - while (!(rdes->rdes3 & STM32_RDES3_OWN)) { - if (!(rdes->rdes3 & STM32_RDES3_ES) - && !(rdes->rdes2 & STM32_RDES2_DAF) -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - && !(rdes->rdes1 & (STM32_RDES1_IPHE | STM32_RDES1_IPCE)) -#endif - && (rdes->rdes3 & STM32_RDES3_FD) && (rdes->rdes3 & STM32_RDES3_LD)) { - /* Found a valid one.*/ - rdp->offset = 0; - rdp->size = (rdes->rdes3 & STM32_RDES3_PL_MASK) -2; /* Lose CRC */ - rdp->physdesc = rdes; - /* Reposition in ring.*/ - macp->rdindex++; - if (macp->rdindex >= STM32_MAC_RECEIVE_BUFFERS) - macp->rdindex = 0; - - return MSG_OK; - } - /* Invalid frame found, purging.*/ - rdes->rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; - /* Reposition in ring.*/ - } - - return MSG_TIMEOUT; -} - -/* - * @brief Releases a receive descriptor. - * @details The descriptor and its buffer are made available for more incoming - * frames. - * - * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure - * - * @notapi - */ -void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { - - osalDbgAssert(!(rdp->physdesc->rdes3 & STM32_RDES3_OWN), - "attempt to release descriptor already owned by DMA"); - - osalSysLock(); - - /* Give buffer back to the Ethernet DMA.*/ - rdp->physdesc->rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; - - /* Wait for the write to rdes3 to go through before resuming the DMA.*/ - __DSB(); - - /* If the DMA engine is stalled then a restart request is issued.*/ - if ((ETH->DMADSR & ETH_DMADSR_RPS) == ETH_DMADSR_RPS_SUSPENDED) { - ETH->DMACSR = ETH_DMACSR_RBU; - } - ETH->DMACRDTPR = 0; - - osalSysUnlock(); -} - -/** - * @brief Updates and returns the link status. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The link status. - * @retval true if the link is active. - * @retval false if the link is down. - * - * @notapi - */ -bool mac_lld_poll_link_status(MACDriver *macp) { - uint32_t maccr, bmsr, bmcr; - - maccr = ETH->MACCR; - - /* PHY CR and SR registers read.*/ - (void)mii_read(macp, MII_BMSR); - bmsr = mii_read(macp, MII_BMSR); - bmcr = mii_read(macp, MII_BMCR); - - /* Check on auto-negotiation mode.*/ - if (bmcr & BMCR_ANENABLE) { - uint32_t lpa; - - /* Auto-negotiation must be finished without faults and link established.*/ - if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) != - (BMSR_LSTATUS | BMSR_ANEGCOMPLETE)) - return macp->link_up = false; - - /* Auto-negotiation enabled, checks the LPA register.*/ - lpa = mii_read(macp, MII_LPA); - - /* Check on link speed.*/ - if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) - maccr |= ETH_MACCR_FES; - else - maccr &= ~ETH_MACCR_FES; - - /* Check on link mode.*/ - if (lpa & (LPA_10FULL | LPA_100FULL)) - maccr |= ETH_MACCR_DM; - else - maccr &= ~ETH_MACCR_DM; - } - else { - /* Link must be established.*/ - if (!(bmsr & BMSR_LSTATUS)) - return macp->link_up = false; - - /* Check on link speed.*/ - if (bmcr & BMCR_SPEED100) - maccr |= ETH_MACCR_FES; - else - maccr &= ~ETH_MACCR_FES; - - /* Check on link mode.*/ - if (bmcr & BMCR_FULLDPLX) - maccr |= ETH_MACCR_DM; - else - maccr &= ~ETH_MACCR_DM; - } - - /* Changes the mode in the MAC.*/ - ETH->MACCR = maccr; - - /* Returns the link status.*/ - return macp->link_up = true; -} - -/** - * @brief Writes to a transmit descriptor's stream. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] buf pointer to the buffer containing the data to be - * written - * @param[in] size number of bytes to be written - * @return The number of bytes written into the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if the maximum - * frame size is reached. - * - * @notapi - */ -size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size) { - - osalDbgAssert(!(tdp->physdesc->tdes3 & STM32_TDES3_OWN), - "attempt to write descriptor already owned by DMA"); - - if (size > tdp->size - tdp->offset) - size = tdp->size - tdp->offset; - - if (size > 0) { - memcpy((uint8_t *)(tdp->physdesc->tdes0) + tdp->offset, buf, size); - tdp->offset += size; - } - return size; -} - -/** - * @brief Reads from a receive descriptor's stream. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] buf pointer to the buffer that will receive the read data - * @param[in] size number of bytes to be read - * @return The number of bytes read from the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if there are - * no more bytes to read. - * - * @notapi - */ -size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size) { - - osalDbgAssert(!(rdp->physdesc->rdes3 & STM32_RDES3_OWN), - "attempt to read descriptor already owned by DMA"); - - if (size > rdp->size - rdp->offset) - size = rdp->size - rdp->offset; - - if (size > 0) { - cacheBufferInvalidate((uint8_t *)(rdp->physdesc->rdes0) + rdp->offset, size); - memcpy(buf, (uint8_t *)(rdp->physdesc->rdes0) + rdp->offset, size); - rdp->offset += size; - } - return size; -} - -#endif /* HAL_USE_MAC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file MACv2/hal_mac_lld.c + * @brief STM32 low level MAC driver code. + * + * @addtogroup MAC + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +#include "hal_mii.h" + +/* Fixes for errors in ST headers.*/ +#if ETH_DMADSR_RPS_FETCHING_Pos == 12 +#undef ETH_DMADSR_RPS_FETCHING_Pos +#define ETH_DMADSR_RPS_FETCHING_Pos (8U) +#endif + +#if ETH_DMADSR_RPS_WAITING_Pos == 12 +#undef ETH_DMADSR_RPS_WAITING_Pos +#define ETH_DMADSR_RPS_WAITING_Pos (9U) +#endif + +#if ETH_DMADSR_RPS_SUSPENDED_Pos == 14 +#undef ETH_DMADSR_RPS_SUSPENDED_Pos +#define ETH_DMADSR_RPS_SUSPENDED_Pos (10U) +#endif + +#if ETH_DMADSR_RPS_CLOSING_Pos == 12 +#undef ETH_DMADSR_RPS_CLOSING_Pos +#define ETH_DMADSR_RPS_CLOSING_Pos (10U) +#endif + +#if ETH_DMADSR_RPS_TIMESTAMP_WR_Pos == 13 +#undef ETH_DMADSR_RPS_TIMESTAMP_WR_Pos +#undef ETH_DMADSR_RPS_TIMESTAMP_WR_Msk +#define ETH_DMADSR_RPS_TIMESTAMP_WR_Pos (10U) +#define ETH_DMADSR_RPS_TIMESTAMP_WR_Msk (0x6UL << ETH_DMADSR_RPS_TIMESTAMP_WR_Pos) +#endif + +#if ETH_DMADSR_RPS_TRANSFERRING_Pos == 12 +#undef ETH_DMADSR_RPS_TRANSFERRING_Pos +#define ETH_DMADSR_RPS_TRANSFERRING_Pos (10U) +#endif + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) + +/* Fixing inconsistencies in ST headers.*/ +#if !defined(ETH_MACMDIOAR_CR_Div124) && defined(ETH_MACMDIOAR_CR_DIV124) +#define ETH_MACMDIOAR_CR_Div124 ETH_MACMDIOAR_CR_DIV124 +#endif +#if !defined(ETH_MACMDIOAR_CR_Div102) && defined(ETH_MACMDIOAR_CR_DIV102) +#define ETH_MACMDIOAR_CR_Div102 ETH_MACMDIOAR_CR_DIV102 +#endif +#if !defined(ETH_MACMDIOAR_CR_Div62) && defined(ETH_MACMDIOAR_CR_DIV62) +#define ETH_MACMDIOAR_CR_Div62 ETH_MACMDIOAR_CR_DIV62 +#endif +#if !defined(ETH_MACMDIOAR_CR_Div42) && defined(ETH_MACMDIOAR_CR_DIV42) +#define ETH_MACMDIOAR_CR_Div42 ETH_MACMDIOAR_CR_DIV42 +#endif +#if !defined(ETH_MACMDIOAR_CR_Div26) && defined(ETH_MACMDIOAR_CR_DIV26) +#define ETH_MACMDIOAR_CR_Div26 ETH_MACMDIOAR_CR_DIV26 +#endif +#if !defined(ETH_MACMDIOAR_CR_Div16) && defined(ETH_MACMDIOAR_CR_DIV16) +#define ETH_MACMDIOAR_CR_Div16 ETH_MACMDIOAR_CR_DIV16 +#endif + +/* MII divider optimal value.*/ +#if (STM32_HCLK > 300000000) +#error "STM32_HCLK above maximum frequency for ETH operations (300MHz)" +#elif (STM32_HCLK >= 250000000) +#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div124 +#elif (STM32_HCLK >= 150000000) +#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div102 +#elif (STM32_HCLK >= 100000000) +#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div62 +#elif (STM32_HCLK >= 60000000) +#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div42 +#elif (STM32_HCLK >= 35000000) +#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div26 +#elif (STM32_HCLK >= 20000000) +#define MACMDIODR_CR ETH_MACMDIOAR_CR_Div16 +#else +#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief Ethernet driver 1. + */ +MACDriver ETHD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13, + 0x37, 0x01, 0x10}; + +static stm32_eth_rx_descriptor_t __eth_rd[STM32_MAC_RECEIVE_BUFFERS] + __attribute__((aligned(4), __section__(".eth"))); +static stm32_eth_tx_descriptor_t __eth_td[STM32_MAC_TRANSMIT_BUFFERS] + __attribute__((aligned(4), __section__(".eth"))); + +static uint32_t __eth_rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE] + __attribute__((aligned(4), __section__(".eth"))); +static uint32_t __eth_tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE] + __attribute__((aligned(4), __section__(".eth"))); + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Writes a PHY register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] reg register number + * @param[in] value new register value + * + * @notapi + */ +void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) { + + ETH->MACMDIODR = value; + ETH->MACMDIOAR = macp->phyaddr | (reg << ETH_MACMDIOAR_RDA_Pos) | MACMDIODR_CR | + ETH_MACMDIOAR_MOC_WR | ETH_MACMDIOAR_MB; + while ((ETH->MACMDIOAR & ETH_MACMDIOAR_MB) != 0) + ; +} + +/** + * @brief Reads a PHY register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] reg register number + * + * @return The PHY register content. + * + * @notapi + */ +uint32_t mii_read(MACDriver *macp, uint32_t reg) { + + ETH->MACMDIOAR = macp->phyaddr | (reg << ETH_MACMDIOAR_RDA_Pos) | MACMDIODR_CR | + ETH_MACMDIOAR_MOC_RD | ETH_MACMDIOAR_MB; + while ((ETH->MACMDIOAR & ETH_MACMDIOAR_MB) != 0) + ; + return ETH->MACMDIODR; +} + +#if !defined(BOARD_PHY_ADDRESS) +/** + * @brief PHY address detection. + * + * @param[in] macp pointer to the @p MACDriver object + */ +static void mii_find_phy(MACDriver *macp) { + uint32_t i; + +#if STM32_MAC_PHY_TIMEOUT > 0 + unsigned n = STM32_MAC_PHY_TIMEOUT; + do { +#endif + for (i = 0U; i <= 31U; i++) { + macp->phyaddr = i << ETH_MACMDIOAR_PA_Pos; + ETH->MACMDIOAR = (i << ETH_MACMDIOAR_RDA_Pos) | MACMDIODR_CR; + ETH->MACMDIODR = (i << ETH_MACMDIODR_RA_Pos) | MACMDIODR_CR; + if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16U)) && + ((mii_read(macp, MII_PHYSID2) & 0xFFF0U) == (BOARD_PHY_ID & 0xFFF0U))) { + return; + } + } +#if STM32_MAC_PHY_TIMEOUT > 0 + n--; + } while (n > 0U); +#endif + /* Wrong or defective board.*/ + osalSysHalt("MAC failure"); +} +#endif + +/** + * @brief MAC address setup. + * + * @param[in] p pointer to a six bytes buffer containing the MAC + * address + */ +static void mac_lld_set_address(const uint8_t *p) { + + /* MAC address configuration, only a single address comparator is used, + hash table not used.*/ + ETH->MACA0HR = ((uint32_t)p[5] << 8) | + ((uint32_t)p[4] << 0); + ETH->MACA0LR = ((uint32_t)p[3] << 24) | + ((uint32_t)p[2] << 16) | + ((uint32_t)p[1] << 8) | + ((uint32_t)p[0] << 0); + ETH->MACA1HR = 0; + ETH->MACA1LR = 0; + ETH->MACA2HR = 0; + ETH->MACA2LR = 0; + ETH->MACA3HR = 0; + ETH->MACA3LR = 0; + ETH->MACHT0R = 0; + ETH->MACHT1R = 0; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +OSAL_IRQ_HANDLER(STM32_ETH_HANDLER) { + uint32_t dmasr; + + OSAL_IRQ_PROLOGUE(); + + dmasr = ETH->DMACSR; + + if (dmasr & ETH_DMACSR_RI) { + /* Data Received.*/ + ETH->DMACSR = ETH_DMACSR_RI; + ETH->DMACIER &= ~ETH_DMACIER_RIE; + osalSysLockFromISR(); + osalThreadDequeueAllI(ÐD1.rdqueue, MSG_RESET); +#if MAC_USE_EVENTS + osalEventBroadcastFlagsI(ÐD1.rdevent, 0); +#endif + osalSysUnlockFromISR(); + } + + if (dmasr & ETH_DMACSR_TI) { + /* Data Transmitted.*/ + ETH->DMACSR = ETH_DMACSR_TI; + osalSysLockFromISR(); + osalThreadDequeueAllI(ÐD1.tdqueue, MSG_RESET); + osalSysUnlockFromISR(); + } + + ETH->DMACSR |= ETH_DMACSR_NIS; + ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE; + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level MAC initialization. + * + * @notapi + */ +void mac_lld_init(void) { + unsigned i,j; + + macObjectInit(ÐD1); + ETHD1.link_up = false; + + /* Descriptor tables are initialized in ring mode, note that the first + word is not initialized here but in mac_lld_start().*/ + for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) { + __eth_rd[i].rdes0 = (uint32_t)__eth_rb[i]; + __eth_rd[i].rdes1 = 0; + __eth_rd[i].rdes2 = 0; + __eth_rd[i].rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; + for (j = 0; j < BUFFER_SIZE; j++) { + __eth_rb[i][j] = 825373492; /* telltale "1234" */ + } + } + for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) { + __eth_td[i].tdes0 = 0; + __eth_td[i].tdes1 = 0; + __eth_td[i].tdes2 = 0; + __eth_td[i].tdes3 = 0; + for (j = 0; j < BUFFER_SIZE; j++) { + __eth_tb[i][j] = 892745528; /* telltale "5678" */ + } + } + + /* Selection of the RMII or MII mode based on info exported by board.h.*/ +#if defined(STM32H7XX) + SYSCFG->PMCR |= SYSCFG_PMCR_PA1SO; +#if defined(BOARD_PHY_RMII) + SYSCFG->PMCR |= SYSCFG_PMCR_EPIS_SEL_2; + SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_1; + SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_0; +#else + SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_2; + SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_1; + SYSCFG->PMCR &= ~SYSCFG_PMCR_EPIS_SEL_0; +#endif +#else +#error "unsupported STM32 platform for MACv2 driver" +#endif + + /* Reset of the MAC core.*/ + rccResetETH(); + + /* MAC clocks temporary activation.*/ + rccEnableETH(true); + + /* PHY address setup.*/ +#if defined(BOARD_PHY_ADDRESS) + ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11; +#else + mii_find_phy(ÐD1); +#endif + +#if defined(BOARD_PHY_RESET) + /* PHY board-specific reset procedure.*/ + BOARD_PHY_RESET(); +#else + /* PHY soft reset procedure.*/ + mii_write(ÐD1, MII_BMCR, BMCR_RESET); +#if defined(BOARD_PHY_RESET_DELAY) + osalSysPolledDelayX(BOARD_PHY_RESET_DELAY); +#endif + while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) + ; +#endif + +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power down mode until the driver will be started.*/ + mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); +#endif + + /* MAC clocks stopped again.*/ + rccDisableETH(); +} + +/** + * @brief Configures and activates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @notapi + */ +void mac_lld_start(MACDriver *macp) { + unsigned i; + + /* Resets the state of all descriptors.*/ + for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) + __eth_rd[i].rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; + macp->rdindex = 0; + for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) + __eth_td[i].tdes3 = 0; + macp->tdindex = 0; + + /* MAC clocks activation and commanded reset procedure.*/ + rccEnableETH(true); + + /* ISR vector enabled.*/ + nvicEnableVector(STM32_ETH_NUMBER, STM32_MAC_ETH1_IRQ_PRIORITY); + +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power up mode.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); +#endif + + ETH->DMAMR |= ETH_DMAMR_SWR; + while (ETH->DMAMR & ETH_DMAMR_SWR) + ; + + /* MAC configuration.*/ + ETH->MACCR = ETH_MACCR_DO; + ETH->MACPFR = 0; + ETH->MACTFCR = 0; + ETH->MACRFCR = 0; + ETH->MACVTR = 0; + + /* MAC address setup.*/ + if (macp->config->mac_address == NULL) + mac_lld_set_address(default_mac_address); + else + mac_lld_set_address(macp->config->mac_address); + + /* Transmitter and receiver enabled. + Note that the complete setup of the MAC is performed when the link + status is detected.*/ +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + ETH->MACCR |= ETH_MACCR_IPC | ETH_MACCR_RE | ETH_MACCR_TE; +#else + ETH->MACCR |= ETH_MACCR_RE | ETH_MACCR_TE; +#endif + + /* DMA general settings.*/ + ETH->DMASBMR = ETH_DMASBMR_AAL; + ETH->DMACCR = ETH_DMACCR_DSL_0BIT; + ETH->DMAMR = ETH_DMAMR_INTM_0 | ETH_DMAMR_PR_8_1 | ETH_DMAMR_TXPR; /* TX:RX 8:1 */ + /* DMA configuration: + Descriptor rings pointers.*/ + ETH->DMACTDLAR = (uint32_t)&__eth_td[0]; + ETH->DMACTDRLR = STM32_MAC_TRANSMIT_BUFFERS-1; + ETH->DMACRDLAR = (uint32_t)&__eth_rd[0]; + ETH->DMACRDRLR = STM32_MAC_RECEIVE_BUFFERS-1; + + /* Enabling required interrupt sources.*/ + ETH->DMACSR = ETH_DMACSR_NIS; + ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE; + + + /* Check because errata on some devices. There should be no need to + disable flushing because the TXFIFO should be empty on macStart().*/ +#if !defined(STM32_MAC_DISABLE_TX_FLUSH) + /* Transmit FIFO flush.*/ + ETH->MTLTQOMR = ETH_MTLTQOMR_FTQ; + while (ETH->MTLTQOMR & ETH_MTLTQOMR_FTQ) + ; +#endif + + /* DMA final configuration and start.*/ + ETH->MTLRQOMR = ETH_MTLRQOMR_DISTCPEF | ETH_MTLRQOMR_RSF; + ETH->MTLTQOMR = ETH_MTLTQOMR_TSF; + ETH->DMACTCR = ETH_DMACTCR_ST | ETH_DMACTCR_TPBL_1PBL; + ETH->DMACRCR = ETH_DMACRCR_SR | ETH_DMACRCR_RPBL_1PBL + | (STM32_MAC_BUFFERS_SIZE << ETH_DMACRCR_RBSZ_Pos + & ETH_DMACRCR_RBSZ); +} + +/** + * @brief Deactivates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @notapi + */ +void mac_lld_stop(MACDriver *macp) { + + if (macp->state != MAC_STOP) { +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power down mode until the driver will be restarted.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); +#endif + + /* MAC and DMA stopped.*/ + ETH->MACCR = 0; + ETH->MTLRQOMR = 0; + ETH->DMACIER = 0; + ETH->DMACSR = ETH->DMACSR; + + /* MAC clocks stopped.*/ + rccDisableETH(); + + /* ISR vector disabled.*/ + nvicDisableVector(STM32_ETH_NUMBER); + } +} + +/** + * @brief Returns a transmission descriptor. + * @details One of the available transmission descriptors is locked and + * returned. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @return The operation status. + * @retval MSG_OK the descriptor has been obtained. + * @retval MSG_TIMEOUT descriptor not available. + * + * @notapi + */ +msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp) { + stm32_eth_tx_descriptor_t *tdes; + + if (!macp->link_up) + return MSG_TIMEOUT; + + /* Get Current TX descriptor.*/ + tdes = (stm32_eth_tx_descriptor_t *)&__eth_td[macp->tdindex]; + + /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by + another thread.*/ + if ((tdes->tdes3 & (STM32_TDES3_OWN)) | (tdes->tdes1 > 0)) { + return MSG_TIMEOUT; + } + + tdes->tdes0 = (uint32_t )__eth_tb[macp->tdindex]; + /* Marks the current descriptor as locked using a reserved bit.*/ + /*tdes->tdes0 |= STM32_TDES0_LOCKED; */ + tdes->tdes1++; + + /* Next TX descriptor to use.*/ + macp->tdindex++; + if (macp->tdindex >= STM32_MAC_TRANSMIT_BUFFERS) + macp->tdindex = 0; + + /* Set the buffer size and configuration.*/ + tdp->offset = 0; + tdp->size = STM32_MAC_BUFFERS_SIZE; + tdp->physdesc = tdes; + + return MSG_OK; +} + +/** + * @brief Releases a transmit descriptor and starts the transmission of the + * enqueued data as a single frame. + * + * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure + * + * @notapi + */ +void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { + + osalDbgAssert(!(tdp->physdesc->tdes3 & STM32_TDES3_OWN), + "attempt to release descriptor already owned by DMA"); + + osalSysLock(); + + /* Unlocks the descriptor and returns it to the DMA engine.*/ + tdp->physdesc->tdes1 = 0; + tdp->physdesc->tdes2 = STM32_TDES2_IOC | (tdp->offset & STM32_TDES2_B1L_MASK); +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + tdp->physdesc->tdes3 = STM32_TDES3_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) | + STM32_TDES3_LD | STM32_TDES3_FD | + STM32_TDES3_OWN; +#else + tdp->physdesc->tdes3 = STM32_TDES3_LD | STM32_TDES3_FD | + STM32_TDES3_OWN; +#endif + + /* Wait for the write to tdes3 to go through before resuming the DMA.*/ + __DSB(); + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMADSR & ETH_DMADSR_TPS) == ETH_DMADSR_TPS_SUSPENDED) { + ETH->DMACSR = ETH_DMACSR_TBU; + } + ETH->DMACTDTPR = 0; + + osalSysUnlock(); +} + +/** + * @brief Returns a receive descriptor. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @return The operation status. + * @retval MSG_OK the descriptor has been obtained. + * @retval MSG_TIMEOUT descriptor not available. + * + * @notapi + */ +msg_t mac_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp) { + stm32_eth_rx_descriptor_t *rdes; + + /* Get Current RX descriptor.*/ + rdes = (stm32_eth_rx_descriptor_t *)&__eth_rd[macp->rdindex]; + + /* Iterates through received frames until a valid one is found, invalid + frames are discarded.*/ + while (!(rdes->rdes3 & STM32_RDES3_OWN)) { + if (!(rdes->rdes3 & STM32_RDES3_ES) + && !(rdes->rdes2 & STM32_RDES2_DAF) +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + && !(rdes->rdes1 & (STM32_RDES1_IPHE | STM32_RDES1_IPCE)) +#endif + && (rdes->rdes3 & STM32_RDES3_FD) && (rdes->rdes3 & STM32_RDES3_LD)) { + /* Found a valid one.*/ + rdp->offset = 0; + rdp->size = (rdes->rdes3 & STM32_RDES3_PL_MASK) -2; /* Lose CRC */ + rdp->physdesc = rdes; + /* Reposition in ring.*/ + macp->rdindex++; + if (macp->rdindex >= STM32_MAC_RECEIVE_BUFFERS) + macp->rdindex = 0; + + return MSG_OK; + } + /* Invalid frame found, purging.*/ + rdes->rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; + /* Reposition in ring.*/ + } + + return MSG_TIMEOUT; +} + +/* + * @brief Releases a receive descriptor. + * @details The descriptor and its buffer are made available for more incoming + * frames. + * + * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure + * + * @notapi + */ +void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { + + osalDbgAssert(!(rdp->physdesc->rdes3 & STM32_RDES3_OWN), + "attempt to release descriptor already owned by DMA"); + + osalSysLock(); + + /* Give buffer back to the Ethernet DMA.*/ + rdp->physdesc->rdes3 = STM32_RDES3_OWN | STM32_RDES3_IOC | STM32_RDES3_BUF1V; + + /* Wait for the write to rdes3 to go through before resuming the DMA.*/ + __DSB(); + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMADSR & ETH_DMADSR_RPS) == ETH_DMADSR_RPS_SUSPENDED) { + ETH->DMACSR = ETH_DMACSR_RBU; + } + ETH->DMACRDTPR = 0; + + osalSysUnlock(); +} + +/** + * @brief Updates and returns the link status. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The link status. + * @retval true if the link is active. + * @retval false if the link is down. + * + * @notapi + */ +bool mac_lld_poll_link_status(MACDriver *macp) { + uint32_t maccr, bmsr, bmcr; + + maccr = ETH->MACCR; + + /* PHY CR and SR registers read.*/ + (void)mii_read(macp, MII_BMSR); + bmsr = mii_read(macp, MII_BMSR); + bmcr = mii_read(macp, MII_BMCR); + + /* Check on auto-negotiation mode.*/ + if (bmcr & BMCR_ANENABLE) { + uint32_t lpa; + + /* Auto-negotiation must be finished without faults and link established.*/ + if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) != + (BMSR_LSTATUS | BMSR_ANEGCOMPLETE)) + return macp->link_up = false; + + /* Auto-negotiation enabled, checks the LPA register.*/ + lpa = mii_read(macp, MII_LPA); + + /* Check on link speed.*/ + if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) + maccr |= ETH_MACCR_FES; + else + maccr &= ~ETH_MACCR_FES; + + /* Check on link mode.*/ + if (lpa & (LPA_10FULL | LPA_100FULL)) + maccr |= ETH_MACCR_DM; + else + maccr &= ~ETH_MACCR_DM; + } + else { + /* Link must be established.*/ + if (!(bmsr & BMSR_LSTATUS)) + return macp->link_up = false; + + /* Check on link speed.*/ + if (bmcr & BMCR_SPEED100) + maccr |= ETH_MACCR_FES; + else + maccr &= ~ETH_MACCR_FES; + + /* Check on link mode.*/ + if (bmcr & BMCR_FULLDPLX) + maccr |= ETH_MACCR_DM; + else + maccr &= ~ETH_MACCR_DM; + } + + /* Changes the mode in the MAC.*/ + ETH->MACCR = maccr; + + /* Returns the link status.*/ + return macp->link_up = true; +} + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be + * written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if the maximum + * frame size is reached. + * + * @notapi + */ +size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size) { + + osalDbgAssert(!(tdp->physdesc->tdes3 & STM32_TDES3_OWN), + "attempt to write descriptor already owned by DMA"); + + if (size > tdp->size - tdp->offset) + size = tdp->size - tdp->offset; + + if (size > 0) { + memcpy((uint8_t *)(tdp->physdesc->tdes0) + tdp->offset, buf, size); + tdp->offset += size; + } + return size; +} + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if there are + * no more bytes to read. + * + * @notapi + */ +size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size) { + + osalDbgAssert(!(rdp->physdesc->rdes3 & STM32_RDES3_OWN), + "attempt to read descriptor already owned by DMA"); + + if (size > rdp->size - rdp->offset) + size = rdp->size - rdp->offset; + + if (size > 0) { + cacheBufferInvalidate((uint8_t *)(rdp->physdesc->rdes0) + rdp->offset, size); + memcpy(buf, (uint8_t *)(rdp->physdesc->rdes0) + rdp->offset, size); + rdp->offset += size; + } + return size; +} + +#endif /* HAL_USE_MAC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.h b/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.h index d756205d24..37c3340c93 100644 --- a/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.h +++ b/os/hal/ports/STM32/LLD/MACv2/hal_mac_lld.h @@ -1,368 +1,368 @@ -/* - ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file MACv2/hal_mac_lld.h - * @brief STM32 low level MAC driver header. - * - * @addtogroup MAC - * @{ - */ - -#ifndef HAL_MAC_LLD_H -#define HAL_MAC_LLD_H - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief This implementation does not support the zero-copy mode API. - */ -#define MAC_SUPPORTS_ZERO_COPY FALSE - -/** - * @name RDES1 constants - * @{ - */ -#define STM32_RDES1_OPC_MASK 0xFFFF0000 -#define STM32_RDES1_TD 0x00008000 -#define STM32_RDES1_TSA 0x00004000 -#define STM32_RDES1_PV 0x00002000 -#define STM32_RDES1_PFT 0x00001000 -#define STM32_RDES1_PMT_MASK 0x00000F00 -#define STM32_RDES1_IPCE 0x00000080 -#define STM32_RDES1_IPCB 0x00000040 -#define STM32_RDES1_IPV6 0x00000020 -#define STM32_RDES1_IPV4 0x00000010 -#define STM32_RDES1_IPHE 0x00000008 -#define STM32_RDES1_PT_MASK 0x00000007 -/** @} */ - -/** - * @name RDES2 constants - * @{ - */ -#define STM32_RDES2_L3L4FM_MASK 0xE0000000 -#define STM32_RDES2_L4FM 0x01000000 -#define STM32_RDES2_L3FM 0x00800000 -#define STM32_RDES2_MADRM_MASK 0x007F8000 -#define STM32_RDES2_HF 0x00004000 -#define STM32_RDES2_DAF 0x00002000 -#define STM32_RDES2_SAF 0x00001000 -#define STM32_RDES2_VF 0x00000800 -#define STM32_RDES2_RES1 0x00000780 -#define STM32_RDES2_ARPNR 0x00000040 -#define STM32_RDES2_RES2 0x0000003F -/** @} */ - -/** - * @name RDES3 constants - * @{ - */ -#define STM32_RDES3_OWN 0x80000000 -#define STM32_RDES3_IOC 0x40000000 /* Read */ -#define STM32_RDES3_CTXT 0x40000000 /* Write */ -#define STM32_RDES3_FD 0x20000000 -#define STM32_RDES3_LD 0x10000000 -#define STM32_RDES3_RS2V 0x08000000 -#define STM32_RDES3_RS1V 0x04000000 -#define STM32_RDES3_BUF2V 0x02000000 /* Read */ -#define STM32_RDES3_RS0V 0x02000000 /* Write */ -#define STM32_RDES3_BUF1V 0x01000000 /* Read */ -#define STM32_RDES3_CE 0x01000000 /* Write */ -#define STM32_RDES3_GP 0x00800000 -#define STM32_RDES3_RWT 0x00400000 -#define STM32_RDES3_OE 0x00200000 -#define STM32_RDES3_RE 0x00100000 -#define STM32_RDES3_DE 0x00080000 -#define STM32_RDES3_LT_MASK 0x00070000 -#define STM32_RDES3_ES 0x00008000 -#define STM32_RDES3_PL_MASK 0x00007FFF -/** @} */ - -/** - * @name TDES2 constants - * @{ - */ -#define STM32_TDES2_IOC 0x80000000 -#define STM32_TDES2_TTSE 0x40000000 -#define STM32_TDES2_B2L_MASK 0x3FFF0000 -#define STM32_TDES2_VTIR_MASK 0x0000C000 -#define STM32_TDES2_VTIR(n) ((n) << 14) -#define STM32_TDES2_B1L_MASK 0x00003FFF -/** @} */ - -/** - * @name TDES3 constants - * @{ - */ -#define STM32_TDES3_OWN 0x80000000 -#define STM32_TDES3_CTXT 0x40000000 -#define STM32_TDES3_FD 0x20000000 -#define STM32_TDES3_LD 0x10000000 -#define STM32_TDES3_CPC_MASK 0x0C000000 -#define STM32_TDES3_CPC(n) ((n) << 26) -#define STM32_TDES3_SAIC_MASK 0x03800000 -#define STM32_TDES3_SAIC(n) ((n) << 23) -#define STM32_TDES3_THL_MASK 0x00780000 -#define STM32_TDES3_THL(n) ((n) << 19) -#define STM32_TDES3_TSE 0x00040000 -#define STM32_TDES3_CIC_MASK 0x00030000 -#define STM32_TDES3_CIC(n) ((n) << 16) -#define STM32_TDES3_TPL 0x00008000 -#define STM32_TDES3_FL 0x00007FFF -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Number of available transmit buffers. - */ -#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) -#define STM32_MAC_TRANSMIT_BUFFERS 4 -#endif - -/** - * @brief Number of available receive buffers. - */ -#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) -#define STM32_MAC_RECEIVE_BUFFERS 4 -#endif - -/** - * @brief Maximum supported frame size. - */ -#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define STM32_MAC_BUFFERS_SIZE 1524 -#endif - -/** - * @brief PHY detection timeout. - * @details Timeout for PHY address detection, the scan for a PHY is performed - * the specified number of times before invoking the failure handler. - * This setting applies only if the PHY address is not explicitly - * set in the board header file using @p BOARD_PHY_ADDRESS. A zero - * value disables the timeout and a single search is performed. - */ -#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_MAC_PHY_TIMEOUT 100 -#endif - -/** - * @brief Change the PHY power state inside the driver. - */ -#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__) -#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE -#endif - -/** - * @brief ETHD1 interrupt priority level setting. - */ -#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_MAC_ETH1_IRQ_PRIORITY 13 -#endif - -/** - * @brief IP checksum offload. - * @details The following modes are available: - * - 0 Function disabled. - * - 1 Only IP header checksum calculation and insertion are enabled. - * - 2 IP header checksum and payload checksum calculation and - * insertion are enabled, but pseudo-header checksum is not - * calculated in hardware. - * - 3 IP Header checksum and payload checksum calculation and - * insertion are enabled, and pseudo-header checksum is - * calculated in hardware. - * . - */ -#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__) -#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an STM32 Ethernet receive descriptor. - */ -typedef struct { - volatile uint32_t rdes0; - volatile uint32_t rdes1; - volatile uint32_t rdes2; - volatile uint32_t rdes3; -} stm32_eth_rx_descriptor_t; - -/** - * @brief Type of an STM32 Ethernet transmit descriptor. - */ -typedef struct { - volatile uint32_t tdes0; - volatile uint32_t tdes1; - volatile uint32_t tdes2; - volatile uint32_t tdes3; -} stm32_eth_tx_descriptor_t; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief MAC address. - */ - uint8_t *mac_address; - /* End of the mandatory fields.*/ -} MACConfig; - -/** - * @brief Structure representing a MAC driver. - */ -struct MACDriver { - /** - * @brief Driver state. - */ - macstate_t state; - /** - * @brief Current configuration data. - */ - const MACConfig *config; - /** - * @brief Transmit semaphore. - */ - threads_queue_t tdqueue; - /** - * @brief Receive semaphore. - */ - threads_queue_t rdqueue; -#if MAC_USE_EVENTS || defined(__DOXYGEN__) - /** - * @brief Receive event. - */ - event_source_t rdevent; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Link status flag. - */ - bool link_up; - /** - * @brief PHY address (pre shifted). - */ - uint32_t phyaddr; - /** - * @brief Receive next frame index. - */ - uint16_t rdindex; - /** - * @brief Transmit next frame index. - */ - uint16_t tdindex; -}; - -/** - * @brief Structure representing a transmit descriptor. - */ -typedef struct { - /** - * @brief Current write offset. - */ - size_t offset; - /** - * @brief Available space size. - */ - size_t size; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the physical descriptor. - */ - stm32_eth_tx_descriptor_t *physdesc; -} MACTransmitDescriptor; - -/** - * @brief Structure representing a receive descriptor. - */ -typedef struct { - /** - * @brief Current read offset. - */ - size_t offset; - /** - * @brief Available data size. - */ - size_t size; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the physical descriptor. - */ - stm32_eth_rx_descriptor_t *physdesc; -} MACReceiveDescriptor; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern MACDriver ETHD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void mii_write(MACDriver *macp, uint32_t reg, uint32_t value); - uint32_t mii_read(MACDriver *macp, uint32_t reg); - void mac_lld_init(void); - void mac_lld_start(MACDriver *macp); - void mac_lld_stop(MACDriver *macp); - msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp); - void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); - msg_t mac_lld_get_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp); - void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); - bool mac_lld_poll_link_status(MACDriver *macp); - size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size); - size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_MAC */ - -#endif /* HAL_MAC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file MACv2/hal_mac_lld.h + * @brief STM32 low level MAC driver header. + * + * @addtogroup MAC + * @{ + */ + +#ifndef HAL_MAC_LLD_H +#define HAL_MAC_LLD_H + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief This implementation does not support the zero-copy mode API. + */ +#define MAC_SUPPORTS_ZERO_COPY FALSE + +/** + * @name RDES1 constants + * @{ + */ +#define STM32_RDES1_OPC_MASK 0xFFFF0000 +#define STM32_RDES1_TD 0x00008000 +#define STM32_RDES1_TSA 0x00004000 +#define STM32_RDES1_PV 0x00002000 +#define STM32_RDES1_PFT 0x00001000 +#define STM32_RDES1_PMT_MASK 0x00000F00 +#define STM32_RDES1_IPCE 0x00000080 +#define STM32_RDES1_IPCB 0x00000040 +#define STM32_RDES1_IPV6 0x00000020 +#define STM32_RDES1_IPV4 0x00000010 +#define STM32_RDES1_IPHE 0x00000008 +#define STM32_RDES1_PT_MASK 0x00000007 +/** @} */ + +/** + * @name RDES2 constants + * @{ + */ +#define STM32_RDES2_L3L4FM_MASK 0xE0000000 +#define STM32_RDES2_L4FM 0x01000000 +#define STM32_RDES2_L3FM 0x00800000 +#define STM32_RDES2_MADRM_MASK 0x007F8000 +#define STM32_RDES2_HF 0x00004000 +#define STM32_RDES2_DAF 0x00002000 +#define STM32_RDES2_SAF 0x00001000 +#define STM32_RDES2_VF 0x00000800 +#define STM32_RDES2_RES1 0x00000780 +#define STM32_RDES2_ARPNR 0x00000040 +#define STM32_RDES2_RES2 0x0000003F +/** @} */ + +/** + * @name RDES3 constants + * @{ + */ +#define STM32_RDES3_OWN 0x80000000 +#define STM32_RDES3_IOC 0x40000000 /* Read */ +#define STM32_RDES3_CTXT 0x40000000 /* Write */ +#define STM32_RDES3_FD 0x20000000 +#define STM32_RDES3_LD 0x10000000 +#define STM32_RDES3_RS2V 0x08000000 +#define STM32_RDES3_RS1V 0x04000000 +#define STM32_RDES3_BUF2V 0x02000000 /* Read */ +#define STM32_RDES3_RS0V 0x02000000 /* Write */ +#define STM32_RDES3_BUF1V 0x01000000 /* Read */ +#define STM32_RDES3_CE 0x01000000 /* Write */ +#define STM32_RDES3_GP 0x00800000 +#define STM32_RDES3_RWT 0x00400000 +#define STM32_RDES3_OE 0x00200000 +#define STM32_RDES3_RE 0x00100000 +#define STM32_RDES3_DE 0x00080000 +#define STM32_RDES3_LT_MASK 0x00070000 +#define STM32_RDES3_ES 0x00008000 +#define STM32_RDES3_PL_MASK 0x00007FFF +/** @} */ + +/** + * @name TDES2 constants + * @{ + */ +#define STM32_TDES2_IOC 0x80000000 +#define STM32_TDES2_TTSE 0x40000000 +#define STM32_TDES2_B2L_MASK 0x3FFF0000 +#define STM32_TDES2_VTIR_MASK 0x0000C000 +#define STM32_TDES2_VTIR(n) ((n) << 14) +#define STM32_TDES2_B1L_MASK 0x00003FFF +/** @} */ + +/** + * @name TDES3 constants + * @{ + */ +#define STM32_TDES3_OWN 0x80000000 +#define STM32_TDES3_CTXT 0x40000000 +#define STM32_TDES3_FD 0x20000000 +#define STM32_TDES3_LD 0x10000000 +#define STM32_TDES3_CPC_MASK 0x0C000000 +#define STM32_TDES3_CPC(n) ((n) << 26) +#define STM32_TDES3_SAIC_MASK 0x03800000 +#define STM32_TDES3_SAIC(n) ((n) << 23) +#define STM32_TDES3_THL_MASK 0x00780000 +#define STM32_TDES3_THL(n) ((n) << 19) +#define STM32_TDES3_TSE 0x00040000 +#define STM32_TDES3_CIC_MASK 0x00030000 +#define STM32_TDES3_CIC(n) ((n) << 16) +#define STM32_TDES3_TPL 0x00008000 +#define STM32_TDES3_FL 0x00007FFF +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Number of available transmit buffers. + */ +#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) +#define STM32_MAC_TRANSMIT_BUFFERS 4 +#endif + +/** + * @brief Number of available receive buffers. + */ +#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) +#define STM32_MAC_RECEIVE_BUFFERS 4 +#endif + +/** + * @brief Maximum supported frame size. + */ +#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define STM32_MAC_BUFFERS_SIZE 1524 +#endif + +/** + * @brief PHY detection timeout. + * @details Timeout for PHY address detection, the scan for a PHY is performed + * the specified number of times before invoking the failure handler. + * This setting applies only if the PHY address is not explicitly + * set in the board header file using @p BOARD_PHY_ADDRESS. A zero + * value disables the timeout and a single search is performed. + */ +#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_MAC_PHY_TIMEOUT 100 +#endif + +/** + * @brief Change the PHY power state inside the driver. + */ +#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__) +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#endif + +/** + * @brief ETHD1 interrupt priority level setting. + */ +#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#endif + +/** + * @brief IP checksum offload. + * @details The following modes are available: + * - 0 Function disabled. + * - 1 Only IP header checksum calculation and insertion are enabled. + * - 2 IP header checksum and payload checksum calculation and + * insertion are enabled, but pseudo-header checksum is not + * calculated in hardware. + * - 3 IP Header checksum and payload checksum calculation and + * insertion are enabled, and pseudo-header checksum is + * calculated in hardware. + * . + */ +#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__) +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an STM32 Ethernet receive descriptor. + */ +typedef struct { + volatile uint32_t rdes0; + volatile uint32_t rdes1; + volatile uint32_t rdes2; + volatile uint32_t rdes3; +} stm32_eth_rx_descriptor_t; + +/** + * @brief Type of an STM32 Ethernet transmit descriptor. + */ +typedef struct { + volatile uint32_t tdes0; + volatile uint32_t tdes1; + volatile uint32_t tdes2; + volatile uint32_t tdes3; +} stm32_eth_tx_descriptor_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief MAC address. + */ + uint8_t *mac_address; + /* End of the mandatory fields.*/ +} MACConfig; + +/** + * @brief Structure representing a MAC driver. + */ +struct MACDriver { + /** + * @brief Driver state. + */ + macstate_t state; + /** + * @brief Current configuration data. + */ + const MACConfig *config; + /** + * @brief Transmit semaphore. + */ + threads_queue_t tdqueue; + /** + * @brief Receive semaphore. + */ + threads_queue_t rdqueue; +#if MAC_USE_EVENTS || defined(__DOXYGEN__) + /** + * @brief Receive event. + */ + event_source_t rdevent; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Link status flag. + */ + bool link_up; + /** + * @brief PHY address (pre shifted). + */ + uint32_t phyaddr; + /** + * @brief Receive next frame index. + */ + uint16_t rdindex; + /** + * @brief Transmit next frame index. + */ + uint16_t tdindex; +}; + +/** + * @brief Structure representing a transmit descriptor. + */ +typedef struct { + /** + * @brief Current write offset. + */ + size_t offset; + /** + * @brief Available space size. + */ + size_t size; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_tx_descriptor_t *physdesc; +} MACTransmitDescriptor; + +/** + * @brief Structure representing a receive descriptor. + */ +typedef struct { + /** + * @brief Current read offset. + */ + size_t offset; + /** + * @brief Available data size. + */ + size_t size; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_rx_descriptor_t *physdesc; +} MACReceiveDescriptor; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern MACDriver ETHD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void mii_write(MACDriver *macp, uint32_t reg, uint32_t value); + uint32_t mii_read(MACDriver *macp, uint32_t reg); + void mac_lld_init(void); + void mac_lld_start(MACDriver *macp); + void mac_lld_stop(MACDriver *macp); + msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp); + void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); + msg_t mac_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp); + void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); + bool mac_lld_poll_link_status(MACDriver *macp); + size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size); + size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_MAC */ + +#endif /* HAL_MAC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MDMAv1/driver.mk b/os/hal/ports/STM32/LLD/MDMAv1/driver.mk index d10e2add0a..710647fe72 100644 --- a/os/hal/ports/STM32/LLD/MDMAv1/driver.mk +++ b/os/hal/ports/STM32/LLD/MDMAv1/driver.mk @@ -1,2 +1,2 @@ -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1 diff --git a/os/hal/ports/STM32/LLD/MDMAv1/notes.txt b/os/hal/ports/STM32/LLD/MDMAv1/notes.txt index a092556a64..5d16ff1961 100644 --- a/os/hal/ports/STM32/LLD/MDMAv1/notes.txt +++ b/os/hal/ports/STM32/LLD/MDMAv1/notes.txt @@ -1,11 +1,11 @@ -STM32 MDMAv1 driver. - -Driver capability: - -- The driver supports the STM32 complex MDMA controller found on H7 - sub-family. - -The file registry must export: - -STM32_MDMA_CHn_HANDLER - Vector name for channel "n" (0..15). -STM32_MDMA_CHn_NUMBER - Vector number for channel "n" (0..15). +STM32 MDMAv1 driver. + +Driver capability: + +- The driver supports the STM32 complex MDMA controller found on H7 + sub-family. + +The file registry must export: + +STM32_MDMA_CHn_HANDLER - Vector name for channel "n" (0..15). +STM32_MDMA_CHn_NUMBER - Vector number for channel "n" (0..15). diff --git a/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c index 2a41ec3b75..fe870fcdad 100644 --- a/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c +++ b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c @@ -1,355 +1,355 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file MDMAv1/stm32_mdma.c - * @brief MDMA helper driver code. - * - * @addtogroup STM32_MDMA - * @details MDMA sharing helper driver. In the STM32 the MDMA channels are a - * shared resource, this driver allows to allocate and free MDMA - * STM32 at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The MDMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating channels. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring MDMA services - has been enabled.*/ -#if defined(STM32_MDMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Global MDMA-related data structures. - */ -static struct { - /** - * @brief Mask of the allocated channels. - */ - uint32_t allocated_mask; - /** - * @brief MDMA IRQ redirectors. - */ - stm32_mdma_channel_t channels[STM32_MDMA_CHANNELS]; -} mdma; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static void mdma_serve_interrupt(const stm32_mdma_channel_t *mdmachp) { - uint32_t flags; - - flags = mdmachp->channel->CISR; - mdmachp->channel->CIFCR = flags; - if (mdmachp->func != NULL) { - mdmachp->func(mdmachp->param, flags); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief MDMA shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_MDMA_HANDLER) { - uint32_t gisr = MDMA->GISR0; - OSAL_IRQ_PROLOGUE(); - - if ((gisr & (1U << 0)) != 0U) { - mdma_serve_interrupt(&mdma.channels[0]); - } - - if ((gisr & (1U << 1)) != 0U) { - mdma_serve_interrupt(&mdma.channels[1]); - } - - if ((gisr & (1U << 2)) != 0U) { - mdma_serve_interrupt(&mdma.channels[2]); - } - - if ((gisr & (1U << 3)) != 0U) { - mdma_serve_interrupt(&mdma.channels[3]); - } - - if ((gisr & (1U << 4)) != 0U) { - mdma_serve_interrupt(&mdma.channels[4]); - } - - if ((gisr & (1U << 5)) != 0U) { - mdma_serve_interrupt(&mdma.channels[5]); - } - - if ((gisr & (1U << 6)) != 0U) { - mdma_serve_interrupt(&mdma.channels[6]); - } - - if ((gisr & (1U << 7)) != 0U) { - mdma_serve_interrupt(&mdma.channels[7]); - } - - if ((gisr & (1U << 8)) != 0U) { - mdma_serve_interrupt(&mdma.channels[8]); - } - - if ((gisr & (1U << 9)) != 0U) { - mdma_serve_interrupt(&mdma.channels[9]); - } - - if ((gisr & (1U << 10)) != 0U) { - mdma_serve_interrupt(&mdma.channels[10]); - } - - if ((gisr & (1U << 11)) != 0U) { - mdma_serve_interrupt(&mdma.channels[11]); - } - - if ((gisr & (1U << 12)) != 0U) { - mdma_serve_interrupt(&mdma.channels[12]); - } - - if ((gisr & (1U << 13)) != 0U) { - mdma_serve_interrupt(&mdma.channels[13]); - } - - if ((gisr & (1U << 14)) != 0U) { - mdma_serve_interrupt(&mdma.channels[14]); - } - - if ((gisr & (1U << 15)) != 0U) { - mdma_serve_interrupt(&mdma.channels[15]); - } - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 MDMA helper initialization. - * - * @init - */ -void mdmaInit(void) { - static MDMA_Channel_TypeDef * const channels[STM32_MDMA_CHANNELS] = { - MDMA_Channel0, MDMA_Channel1, MDMA_Channel2, MDMA_Channel3, - MDMA_Channel4, MDMA_Channel5, MDMA_Channel6, MDMA_Channel7, - MDMA_Channel8, MDMA_Channel9, MDMA_Channel10, MDMA_Channel11, - MDMA_Channel12, MDMA_Channel13, MDMA_Channel14, MDMA_Channel15 - }; - unsigned i; - - mdma.allocated_mask = 0U; - for (i = 0U; i < STM32_MDMA_CHANNELS; i++) { - MDMA_Channel_TypeDef *cp = channels[i]; - mdma.channels[i].channel = cp; - mdma.channels[i].func = NULL; - mdma.channels[i].channel->CCR = STM32_MDMA_CCR_RESET_VALUE; - mdma.channels[i].channel->CTCR = STM32_MDMA_CTCR_RESET_VALUE; - mdma.channels[i].channel->CIFCR = STM32_MDMA_CIFCR_CTEIF | - STM32_MDMA_CIFCR_CBRTIF | - STM32_MDMA_CIFCR_CBRTIF | - STM32_MDMA_CIFCR_CCTCIF | - STM32_MDMA_CIFCR_CTEIF; - } -} - -/** - * @brief Allocates an MDMA channel. - * @details The channel is allocated and, if required, the MDMA clock enabled. - * The function also enables the IRQ vector associated to the channel - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific channel or: - * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel. - * . - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_mdma_channel_t - * structure. - * @retval NULL if a/the channel is not available. - * - * @iclass - */ -const stm32_mdma_channel_t *mdmaChannelAllocI(uint32_t id, - stm32_mdmaisr_t func, - void *param) { - uint32_t i, startid, endid; - - osalDbgCheckClassI(); - - if (id < STM32_MDMA_CHANNELS) { - startid = id; - endid = id; - } - else if (id == STM32_MDMA_CHANNEL_ID_ANY) { - startid = 0U; - endid = STM32_MDMA_CHANNELS - 1U; - } - else { - osalDbgCheck(false); - return NULL; - } - - for (i = startid; i <= endid; i++) { - uint32_t mask = (1U << i); - if ((mdma.allocated_mask & mask) == 0U) { - stm32_mdma_channel_t *mdmachp = &mdma.channels[i]; - - /* Installs the MDMA handler.*/ - mdma.allocated_mask |= mask; - mdmachp->func = func; - mdmachp->param = param; - - /* Enabling MDMA clocks required by the current channels set.*/ - if (mdma.allocated_mask != 0U) { - rccEnableMDMA(true); - } - - return mdmachp; - } - } - - return NULL; -} - -/** - * @brief Allocates a MDMA channel. - * @details The channel is allocated and, if required, the MDMA clock enabled. - * The function also enables the IRQ vector associated to the channel - * and initializes its priority. - * - * @param[in] id numeric identifiers of a specific channel or: - * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel. - * . - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return Pointer to the allocated @p stm32_mdma_channel_t - * structure. - * @retval NULL if a/the channel is not available. - * - * @api - */ -const stm32_mdma_channel_t *mdmaChannelAlloc(uint32_t id, - stm32_mdmaisr_t func, - void *param) { - const stm32_mdma_channel_t *mdmachp; - - osalSysLock(); - mdmachp = mdmaChannelAllocI(id, func, param); - osalSysUnlock(); - - return mdmachp; -} - -/** - * @brief Releases a MDMA channel. - * @details The channel is freed and, if required, the MDMA clock disabled. - * Trying to release a unallocated channel is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * - * @iclass - */ -void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp) { - uint32_t channel = mdmachp - mdma.channels; - osalDbgCheck(mdmachp != NULL); - - /* Check if the channels is not taken.*/ - osalDbgAssert((mdma.allocated_mask & (1U << channel)) != 0U, - "not allocated"); - - /* Marks the channel as not allocated.*/ - mdma.allocated_mask &= ~(1U << channel); - - /* Shutting down clocks that are no more required, if any.*/ - if (mdma.allocated_mask == 0U) { - rccDisableMDMA(); - } -} - -/** - * @brief Releases a MDMA channel. - * @details The channel is freed and, if required, the MDMA clock disabled. - * Trying to release a unallocated channel is an illegal operation - * and is trapped if assertions are enabled. - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * - * @api - */ -void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp) { - - osalSysLock(); - mdmaChannelFreeI(mdmachp); - osalSysUnlock(); -} - -/** - * @brief MDMA stream disable. - * @details The function disables the specified stream, waits for the disable - * operation to complete and then clears any pending interrupt. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * - * @xclass - */ -void mdmaChannelDisableX(const stm32_mdma_channel_t *mdmachp) { - uint32_t ccr = mdmachp->channel->CCR; - - /* Clearing CCR regardless of previous state.*/ - mdmachp->channel->CCR &= ~(STM32_MDMA_CCR_TCIE | STM32_MDMA_CCR_BTIE | - STM32_MDMA_CCR_BRTIE | STM32_MDMA_CCR_CTCIE | - STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_EN); - - /* If the channel was enabled then waiting for ongoing operations - to finish.*/ - if ((ccr & STM32_MDMA_CCR_EN) != 0U) { - while (((mdmachp)->channel->CISR & STM32_MDMA_CISR_CTCIF) == 0U) - ; - } - - /* Clearing IRQ sources.*/ - mdmaChannelClearInterruptX(mdmachp); -} - -#endif /* defined(STM32_MDMA_REQUIRED) */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file MDMAv1/stm32_mdma.c + * @brief MDMA helper driver code. + * + * @addtogroup STM32_MDMA + * @details MDMA sharing helper driver. In the STM32 the MDMA channels are a + * shared resource, this driver allows to allocate and free MDMA + * STM32 at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The MDMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating channels. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring MDMA services + has been enabled.*/ +#if defined(STM32_MDMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Global MDMA-related data structures. + */ +static struct { + /** + * @brief Mask of the allocated channels. + */ + uint32_t allocated_mask; + /** + * @brief MDMA IRQ redirectors. + */ + stm32_mdma_channel_t channels[STM32_MDMA_CHANNELS]; +} mdma; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void mdma_serve_interrupt(const stm32_mdma_channel_t *mdmachp) { + uint32_t flags; + + flags = mdmachp->channel->CISR; + mdmachp->channel->CIFCR = flags; + if (mdmachp->func != NULL) { + mdmachp->func(mdmachp->param, flags); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief MDMA shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_HANDLER) { + uint32_t gisr = MDMA->GISR0; + OSAL_IRQ_PROLOGUE(); + + if ((gisr & (1U << 0)) != 0U) { + mdma_serve_interrupt(&mdma.channels[0]); + } + + if ((gisr & (1U << 1)) != 0U) { + mdma_serve_interrupt(&mdma.channels[1]); + } + + if ((gisr & (1U << 2)) != 0U) { + mdma_serve_interrupt(&mdma.channels[2]); + } + + if ((gisr & (1U << 3)) != 0U) { + mdma_serve_interrupt(&mdma.channels[3]); + } + + if ((gisr & (1U << 4)) != 0U) { + mdma_serve_interrupt(&mdma.channels[4]); + } + + if ((gisr & (1U << 5)) != 0U) { + mdma_serve_interrupt(&mdma.channels[5]); + } + + if ((gisr & (1U << 6)) != 0U) { + mdma_serve_interrupt(&mdma.channels[6]); + } + + if ((gisr & (1U << 7)) != 0U) { + mdma_serve_interrupt(&mdma.channels[7]); + } + + if ((gisr & (1U << 8)) != 0U) { + mdma_serve_interrupt(&mdma.channels[8]); + } + + if ((gisr & (1U << 9)) != 0U) { + mdma_serve_interrupt(&mdma.channels[9]); + } + + if ((gisr & (1U << 10)) != 0U) { + mdma_serve_interrupt(&mdma.channels[10]); + } + + if ((gisr & (1U << 11)) != 0U) { + mdma_serve_interrupt(&mdma.channels[11]); + } + + if ((gisr & (1U << 12)) != 0U) { + mdma_serve_interrupt(&mdma.channels[12]); + } + + if ((gisr & (1U << 13)) != 0U) { + mdma_serve_interrupt(&mdma.channels[13]); + } + + if ((gisr & (1U << 14)) != 0U) { + mdma_serve_interrupt(&mdma.channels[14]); + } + + if ((gisr & (1U << 15)) != 0U) { + mdma_serve_interrupt(&mdma.channels[15]); + } + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 MDMA helper initialization. + * + * @init + */ +void mdmaInit(void) { + static MDMA_Channel_TypeDef * const channels[STM32_MDMA_CHANNELS] = { + MDMA_Channel0, MDMA_Channel1, MDMA_Channel2, MDMA_Channel3, + MDMA_Channel4, MDMA_Channel5, MDMA_Channel6, MDMA_Channel7, + MDMA_Channel8, MDMA_Channel9, MDMA_Channel10, MDMA_Channel11, + MDMA_Channel12, MDMA_Channel13, MDMA_Channel14, MDMA_Channel15 + }; + unsigned i; + + mdma.allocated_mask = 0U; + for (i = 0U; i < STM32_MDMA_CHANNELS; i++) { + MDMA_Channel_TypeDef *cp = channels[i]; + mdma.channels[i].channel = cp; + mdma.channels[i].func = NULL; + mdma.channels[i].channel->CCR = STM32_MDMA_CCR_RESET_VALUE; + mdma.channels[i].channel->CTCR = STM32_MDMA_CTCR_RESET_VALUE; + mdma.channels[i].channel->CIFCR = STM32_MDMA_CIFCR_CTEIF | + STM32_MDMA_CIFCR_CBRTIF | + STM32_MDMA_CIFCR_CBRTIF | + STM32_MDMA_CIFCR_CCTCIF | + STM32_MDMA_CIFCR_CTEIF; + } +} + +/** + * @brief Allocates an MDMA channel. + * @details The channel is allocated and, if required, the MDMA clock enabled. + * The function also enables the IRQ vector associated to the channel + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific channel or: + * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel. + * . + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_mdma_channel_t + * structure. + * @retval NULL if a/the channel is not available. + * + * @iclass + */ +const stm32_mdma_channel_t *mdmaChannelAllocI(uint32_t id, + stm32_mdmaisr_t func, + void *param) { + uint32_t i, startid, endid; + + osalDbgCheckClassI(); + + if (id < STM32_MDMA_CHANNELS) { + startid = id; + endid = id; + } + else if (id == STM32_MDMA_CHANNEL_ID_ANY) { + startid = 0U; + endid = STM32_MDMA_CHANNELS - 1U; + } + else { + osalDbgCheck(false); + return NULL; + } + + for (i = startid; i <= endid; i++) { + uint32_t mask = (1U << i); + if ((mdma.allocated_mask & mask) == 0U) { + stm32_mdma_channel_t *mdmachp = &mdma.channels[i]; + + /* Installs the MDMA handler.*/ + mdma.allocated_mask |= mask; + mdmachp->func = func; + mdmachp->param = param; + + /* Enabling MDMA clocks required by the current channels set.*/ + if (mdma.allocated_mask != 0U) { + rccEnableMDMA(true); + } + + return mdmachp; + } + } + + return NULL; +} + +/** + * @brief Allocates a MDMA channel. + * @details The channel is allocated and, if required, the MDMA clock enabled. + * The function also enables the IRQ vector associated to the channel + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific channel or: + * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel. + * . + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_mdma_channel_t + * structure. + * @retval NULL if a/the channel is not available. + * + * @api + */ +const stm32_mdma_channel_t *mdmaChannelAlloc(uint32_t id, + stm32_mdmaisr_t func, + void *param) { + const stm32_mdma_channel_t *mdmachp; + + osalSysLock(); + mdmachp = mdmaChannelAllocI(id, func, param); + osalSysUnlock(); + + return mdmachp; +} + +/** + * @brief Releases a MDMA channel. + * @details The channel is freed and, if required, the MDMA clock disabled. + * Trying to release a unallocated channel is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @iclass + */ +void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp) { + uint32_t channel = mdmachp - mdma.channels; + osalDbgCheck(mdmachp != NULL); + + /* Check if the channels is not taken.*/ + osalDbgAssert((mdma.allocated_mask & (1U << channel)) != 0U, + "not allocated"); + + /* Marks the channel as not allocated.*/ + mdma.allocated_mask &= ~(1U << channel); + + /* Shutting down clocks that are no more required, if any.*/ + if (mdma.allocated_mask == 0U) { + rccDisableMDMA(); + } +} + +/** + * @brief Releases a MDMA channel. + * @details The channel is freed and, if required, the MDMA clock disabled. + * Trying to release a unallocated channel is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @api + */ +void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp) { + + osalSysLock(); + mdmaChannelFreeI(mdmachp); + osalSysUnlock(); +} + +/** + * @brief MDMA stream disable. + * @details The function disables the specified stream, waits for the disable + * operation to complete and then clears any pending interrupt. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @xclass + */ +void mdmaChannelDisableX(const stm32_mdma_channel_t *mdmachp) { + uint32_t ccr = mdmachp->channel->CCR; + + /* Clearing CCR regardless of previous state.*/ + mdmachp->channel->CCR &= ~(STM32_MDMA_CCR_TCIE | STM32_MDMA_CCR_BTIE | + STM32_MDMA_CCR_BRTIE | STM32_MDMA_CCR_CTCIE | + STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_EN); + + /* If the channel was enabled then waiting for ongoing operations + to finish.*/ + if ((ccr & STM32_MDMA_CCR_EN) != 0U) { + while (((mdmachp)->channel->CISR & STM32_MDMA_CISR_CTCIF) == 0U) + ; + } + + /* Clearing IRQ sources.*/ + mdmaChannelClearInterruptX(mdmachp); +} + +#endif /* defined(STM32_MDMA_REQUIRED) */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h index bdc8bbbf98..8fcaf131a1 100644 --- a/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h +++ b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h @@ -1,462 +1,462 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file MDMAv1/stm32_mdma.h - * @brief MDMA helper driver header. - * - * @addtogroup STM32_MDMA - * @{ - */ - -#ifndef STM32_MDMA_H -#define STM32_MDMA_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Total number of MDMA streams. - */ -#define STM32_MDMA_CHANNELS 16U - -/** - * @brief Mask of the ISR bits passed to the MDMA callback functions. - */ -#define STM32_MDMA_ISR_MASK 0x1FU - -/** - * @brief Checks if a MDMA priority is within the valid range. - * @param[in] prio MDMA priority - * - * @retval The check result. - * @retval false invalid MDMA priority. - * @retval true correct MDMA priority. - */ -#define STM32_MDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) - -/** - * @brief Checks if a MDMA channel id is within the valid range. - * - * @param[in] id MDMA channel id - * @retval The check result. - * @retval false invalid MDMA channel. - * @retval true correct MDMA channel. - */ -#define STM32_MDMA_IS_VALID_CHANNEL(id) (((id) >= 0U) && \ - ((id) <= STM32_MDMA_CHANNELS)) - -/** - * @brief Special stream identifier - */ -#define STM32_MDMA_CHANNEL_ID_ANY STM32_MDMA_CHANNELS - -/** - * @name CISR register constants - * @{ - */ -#define STM32_MDMA_CISR_TEIF (1U << 0) -#define STM32_MDMA_CISR_CTCIF (1U << 1) -#define STM32_MDMA_CISR_BRTIF (1U << 2) -#define STM32_MDMA_CISR_BTIF (1U << 3) -#define STM32_MDMA_CISR_TCIF (1U << 4) -#define STM32_MDMA_CISR_CRQA (1U << 16) -/** @} */ - -/** - * @name CIFCR register constants - * @{ - */ -#define STM32_MDMA_CIFCR_CTEIF (1U << 0) -#define STM32_MDMA_CIFCR_CCTCIF (1U << 1) -#define STM32_MDMA_CIFCR_CBRTIF (1U << 2) -#define STM32_MDMA_CIFCR_CBTIF (1U << 3) -#define STM32_MDMA_CIFCR_CTCIF (1U << 4) -/** @} */ - -/** - * @name CESR register constants - * @{ - */ -#define STM32_MDMA_CESR_TEA_MASK (127U << 0) -#define STM32_MDMA_CESR_TED (1U << 7) -#define STM32_MDMA_CESR_TELD (1U << 8) -#define STM32_MDMA_CESR_TEMD (1U << 9) -#define STM32_MDMA_CESR_ASE (1U << 10) -#define STM32_MDMA_CESR_BSE (1U << 11) -/** @} */ - -/** - * @name CCR register constants - * @{ - */ -#define STM32_MDMA_CCR_RESET_VALUE 0x00000000U -#define STM32_MDMA_CCR_EN (1U << 0) -#define STM32_MDMA_CCR_TEIE (1U << 1) -#define STM32_MDMA_CCR_CTCIE (1U << 2) -#define STM32_MDMA_CCR_BRTIE (1U << 3) -#define STM32_MDMA_CCR_BTIE (1U << 4) -#define STM32_MDMA_CCR_TCIE (1U << 5) -#define STM32_MDMA_CCR_PL_MASK (3U << 6) -#define STM32_MDMA_CCR_PL(n) ((n) << 6) -#define STM32_MDMA_CCR_BEX (1U << 12) -#define STM32_MDMA_CCR_HEX (1U << 13) -#define STM32_MDMA_CCR_WEX (1U << 14) -#define STM32_MDMA_CCR_SWRQ (1U << 16) -/** @} */ - -/** - * @name CTCR register constants - * @{ - */ -#define STM32_MDMA_CTCR_RESET_VALUE 0x00000000U - -#define STM32_MDMA_CTCR_SINC_MASK (3U << 0) -#define STM32_MDMA_CTCR_SINC(n) ((n) << 0) -#define STM32_MDMA_CTCR_SINC_FIXED STM32_MDMA_CTCR_SINC(0U) -#define STM32_MDMA_CTCR_SINC_INC STM32_MDMA_CTCR_SINC(2U) -#define STM32_MDMA_CTCR_SINC_DEC STM32_MDMA_CTCR_SINC(3U) - -#define STM32_MDMA_CTCR_DINC_MASK (3U << 2) -#define STM32_MDMA_CTCR_DINC(n) ((n) << 2) -#define STM32_MDMA_CTCR_DINC_FIXED STM32_MDMA_CTCR_DINC(0U) -#define STM32_MDMA_CTCR_DINC_INC STM32_MDMA_CTCR_DINC(2U) -#define STM32_MDMA_CTCR_DINC_DEC STM32_MDMA_CTCR_DINC(3U) - -#define STM32_MDMA_CTCR_SSIZE_MASK (3U << 4) -#define STM32_MDMA_CTCR_SSIZE(n) ((n) << 4) -#define STM32_MDMA_CTCR_SSIZE_BYTE STM32_MDMA_CTCR_SSIZE(0U) -#define STM32_MDMA_CTCR_SSIZE_HALF STM32_MDMA_CTCR_SSIZE(1U) -#define STM32_MDMA_CTCR_SSIZE_WORD STM32_MDMA_CTCR_SSIZE(2U) -#define STM32_MDMA_CTCR_SSIZE_DWORD STM32_MDMA_CTCR_SSIZE(3U) - -#define STM32_MDMA_CTCR_DSIZE_MASK (3U << 6) -#define STM32_MDMA_CTCR_DSIZE(n) ((n) << 6) -#define STM32_MDMA_CTCR_DSIZE_BYTE STM32_MDMA_CTCR_DSIZE(0U) -#define STM32_MDMA_CTCR_DSIZE_HALF STM32_MDMA_CTCR_DSIZE(1U) -#define STM32_MDMA_CTCR_DSIZE_WORD STM32_MDMA_CTCR_DSIZE(2U) -#define STM32_MDMA_CTCR_DSIZE_DWORD STM32_MDMA_CTCR_DSIZE(3U) - -#define STM32_MDMA_CTCR_SINCOS_MASK (3U << 8) -#define STM32_MDMA_CTCR_SINCOS(n) ((n) << 8) -#define STM32_MDMA_CTCR_SINCOS_BYTE STM32_MDMA_CTCR_SINCOS(0U) -#define STM32_MDMA_CTCR_SINCOS_HALF STM32_MDMA_CTCR_SINCOS(1U) -#define STM32_MDMA_CTCR_SINCOS_WORD STM32_MDMA_CTCR_SINCOS(2U) -#define STM32_MDMA_CTCR_SINCOS_DWORD STM32_MDMA_CTCR_SINCOS(3U) - -#define STM32_MDMA_CTCR_DINCOS_MASK (3U << 10) -#define STM32_MDMA_CTCR_DINCOS(n) ((n) << 10) -#define STM32_MDMA_CTCR_DINCOS_BYTE STM32_MDMA_CTCR_DINCOS(0U) -#define STM32_MDMA_CTCR_DINCOS_HALF STM32_MDMA_CTCR_DINCOS(1U) -#define STM32_MDMA_CTCR_DINCOS_WORD STM32_MDMA_CTCR_DINCOS(2U) -#define STM32_MDMA_CTCR_DINCOS_DWORD STM32_MDMA_CTCR_DINCOS(3U) - -#define STM32_MDMA_CTCR_SBURST_MASK (7U << 12) -#define STM32_MDMA_CTCR_SBURST(n) ((n) << 12) -#define STM32_MDMA_CTCR_SBURST_1 STM32_MDMA_CTCR_SBURST(0U) -#define STM32_MDMA_CTCR_SBURST_2 STM32_MDMA_CTCR_SBURST(1U) -#define STM32_MDMA_CTCR_SBURST_4 STM32_MDMA_CTCR_SBURST(2U) -#define STM32_MDMA_CTCR_SBURST_8 STM32_MDMA_CTCR_SBURST(3U) -#define STM32_MDMA_CTCR_SBURST_16 STM32_MDMA_CTCR_SBURST(4U) -#define STM32_MDMA_CTCR_SBURST_32 STM32_MDMA_CTCR_SBURST(5U) -#define STM32_MDMA_CTCR_SBURST_64 STM32_MDMA_CTCR_SBURST(6U) -#define STM32_MDMA_CTCR_SBURST_128 STM32_MDMA_CTCR_SBURST(7U) - -#define STM32_MDMA_CTCR_DBURST_MASK (7U << 15) -#define STM32_MDMA_CTCR_DBURST(n) ((n) << 15) -#define STM32_MDMA_CTCR_DBURST_1 STM32_MDMA_CTCR_DBURST(0U) -#define STM32_MDMA_CTCR_DBURST_2 STM32_MDMA_CTCR_DBURST(1U) -#define STM32_MDMA_CTCR_DBURST_4 STM32_MDMA_CTCR_DBURST(2U) -#define STM32_MDMA_CTCR_DBURST_8 STM32_MDMA_CTCR_DBURST(3U) -#define STM32_MDMA_CTCR_DBURST_16 STM32_MDMA_CTCR_DBURST(4U) -#define STM32_MDMA_CTCR_DBURST_32 STM32_MDMA_CTCR_DBURST(5U) -#define STM32_MDMA_CTCR_DBURST_64 STM32_MDMA_CTCR_DBURST(6U) -#define STM32_MDMA_CTCR_DBURST_128 STM32_MDMA_CTCR_DBURST(7U) - -#define STM32_MDMA_CTCR_TLEN_MASK (127U << 18) -#define STM32_MDMA_CTCR_TLEN(n) ((n) << 18) - -#define STM32_MDMA_CTCR_PKE (1U << 25) - -#define STM32_MDMA_CTCR_PAM_MASK (3U << 26) -#define STM32_MDMA_CTCR_PAM(n) ((n) << 26) -#define STM32_MDMA_CTCR_PAM_RIGHT STM32_MDMA_CTCR_PAM(0U) -#define STM32_MDMA_CTCR_PAM_RIGHT_SE STM32_MDMA_CTCR_PAM(1U) -#define STM32_MDMA_CTCR_PAM_LEFT STM32_MDMA_CTCR_PAM(2U) - -#define STM32_MDMA_CTCR_TRGM_MASK (3U << 28) -#define STM32_MDMA_CTCR_TRGM(n) ((n) << 28) -#define STM32_MDMA_CTCR_TRGM_BUFFER STM32_MDMA_CTCR_TRGM(0U) -#define STM32_MDMA_CTCR_TRGM_BLOCK STM32_MDMA_CTCR_TRGM(1U) -#define STM32_MDMA_CTCR_TRGM_REP_BLOCK STM32_MDMA_CTCR_TRGM(2U) -#define STM32_MDMA_CTCR_TRGM_WHOLE STM32_MDMA_CTCR_TRGM(3U) - -#define STM32_MDMA_CTCR_SWRM (1U << 30) - -#define STM32_MDMA_CTCR_BWM_MASK (1U << 31) -#define STM32_MDMA_CTCR_BWM_NON_BUFF (0U << 31) -#define STM32_MDMA_CTCR_BWM_BUFF (1U << 31) -/** @} */ - -/** - * @name BNDTR register constants - * @{ - */ -#define STM32_MDMA_CBNDTR_BNDT_MASK (0x1FFFFU << 0) -#define STM32_MDMA_CBNDTR_BNDT(n) ((n) << 0) -#define STM32_MDMA_CBNDTR_BRSUM (1U << 18) -#define STM32_MDMA_CBNDTR_BRDUM (1U << 19) -#define STM32_MDMA_CBNDTR_BRC_MASK (0xFFFU << 20) -#define STM32_MDMA_CBNDTR_BRC(n) ((n) << 20) -/** @} */ - -/** - * @name CBRUR register constants - * @{ - */ -#define STM32_MDMA_CBRUR_SUV_MASK (0xFFFFU << 0) -#define STM32_MDMA_CBRUR_SUV(n) ((n) << 0) -#define STM32_MDMA_CBRUR_DUV_MASK (0xFFFFU << 16) -#define STM32_MDMA_CBRUR_DUV(n) ((n) << 16) -/** @} */ - -/** - * @name CTBR register constants - * @{ - */ -#define STM32_MDMA_CTBR_TSEL_MASK (0x3FU << 0) -#define STM32_MDMA_CTBR_TSEL(n) ((n) << 0) -#define STM32_MDMA_CTBR_TSEL_SBUS (1U << 16) -#define STM32_MDMA_CTBR_TSEL_DBUS (1U << 17) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_MDMA_HANDLER) -#error "STM32_MDMA_HANDLER missing in registry" -#endif - -#if !defined(STM32_MDMA_NUMBER) -#error "STM32_MDMA_NUMBER missing in registry" -#endif - -/* Priority settings checks.*/ -#if !defined(STM32_IRQ_MDMA_PRIORITY) -#error "STM32_IRQ_MDMA_PRIORITY not defined in mcuconf.h" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_MDMA_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_MDMA_PRIORITY" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 MDMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags content of the CISR register - */ -typedef void (*stm32_mdmaisr_t)(void *p, uint32_t flags); - -/** - * @brief STM32 MDMA stream descriptor structure. - */ -typedef struct { - /** - * @brief Associated MDMA channel. - */ - MDMA_Channel_TypeDef *channel; - /** - * @brief MDMA callback function. - */ - stm32_mdmaisr_t func; - /** - * @brief MDMA callback parameter. - */ - void *param; -} stm32_mdma_channel_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Associates a source address to a MDMA stream. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * @param[in] addr value to be written in the CSAR register - * - * @xclass - */ -#define mdmaChannelSetSourceX(mdmachp, addr) do { \ - (mdmachp)->channel->CSAR = (uint32_t)(addr); \ -} while (0) - -/** - * @brief Associates a memory destination to a MDMA stream. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * @param[in] addr value to be written in the CDAR register - * - * @xclass - */ -#define mdmaChannelSetDestinationX(mdmachp, addr) do { \ - (mdmachp)->channel->CDAR = (uint32_t)(addr); \ -} while (0) - -/** - * @brief Sets parameters related to the transaction size. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * @param[in] size number of bytes per block - * @param[in] n number of blocks repetitions - * @param[in] opt other option bits for the CBNDTR register - * - * @xclass - */ -#define mdmaChannelSetTransactionSizeX(mdmachp, size, n, opt) do { \ - (mdmachp)->channel->CBNDTR = (uint32_t)STM32_MDMA_CBNDTR_BNDT(size) | \ - (uint32_t)STM32_MDMA_CBNDTR_BRC(n) | \ - (uint32_t)opt; \ -} while (0) - -/** - * @brief Programs the stream mode settings. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * @param[in] ctcr value to be written in the CTCR register - * @param[in] ccr value to be written in the CCR register - * - * @xclass - */ -#define mdmaChannelSetModeX(mdmachp, ctcr, ccr) do { \ - (mdmachp)->channel->CTCR = (uint32_t)(ctcr); \ - (mdmachp)->channel->CCR = (uint32_t)(ccr); \ -} while (0) - -/** - * @brief Programs the trigger mode settings. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * @param[in] tsel value to be written in the CTBR register - * - * @xclass - */ -#define mdmaChannelSetTrigModeX(mdmachp, tsel) do { \ - (mdmachp)->channel->CTBR = STM32_MDMA_CTBR_TSEL(tsel); \ -} while (0) - -/** - * @brief MDMA stream enable. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * - * @xclass - */ -#define mdmaChannelEnableX(mdmachp) do { \ - (mdmachp)->channel->CCR |= STM32_MDMA_CCR_EN; \ -} while (0) - -/** - * @brief Channel enable check. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - */ -#define mdmaChannelIsEnabled(mdmachp) \ - (((mdmachp)->channel->CCR & STM32_MDMA_CCR_EN) != 0U) - -/** - * @brief MDMA stream interrupt sources clear. - * @pre The stream must have been allocated using @p mdmaChannelAlloc(). - * @post After use the stream can be released using @p mdmaChannelFree(). - * - * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure - * - * @xclass - */ -#define mdmaChannelClearInterruptX(mdmachp) do { \ - (mdmachp)->channel->CIFCR = (STM32_MDMA_CIFCR_CTEIF | \ - STM32_MDMA_CIFCR_CBRTIF | \ - STM32_MDMA_CIFCR_CBRTIF | \ - STM32_MDMA_CIFCR_CCTCIF | \ - STM32_MDMA_CIFCR_CTEIF); \ -} while (0) - -/** - * @brief MDMA IRQ enable. - */ -#define mdma_irq_init() \ - nvicEnableVector(STM32_MDMA_NUMBER, STM32_IRQ_MDMA_PRIORITY) - -/** - * @brief MDMA IRQ disable. - */ -#define mdma_irq_deinit() \ - nvicDisableVector(STM32_MDMA_NUMBER) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void mdmaInit(void); - const stm32_mdma_channel_t *mdmaChannelAllocI(uint32_t id, - stm32_mdmaisr_t func, - void *param); - const stm32_mdma_channel_t *mdmaChannelAlloc(uint32_t id, - stm32_mdmaisr_t func, - void *param); - void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp); - void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp); - void mdmaChannelDisableX(const stm32_mdma_channel_t *mdmachp); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_MDMA_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file MDMAv1/stm32_mdma.h + * @brief MDMA helper driver header. + * + * @addtogroup STM32_MDMA + * @{ + */ + +#ifndef STM32_MDMA_H +#define STM32_MDMA_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of MDMA streams. + */ +#define STM32_MDMA_CHANNELS 16U + +/** + * @brief Mask of the ISR bits passed to the MDMA callback functions. + */ +#define STM32_MDMA_ISR_MASK 0x1FU + +/** + * @brief Checks if a MDMA priority is within the valid range. + * @param[in] prio MDMA priority + * + * @retval The check result. + * @retval false invalid MDMA priority. + * @retval true correct MDMA priority. + */ +#define STM32_MDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) + +/** + * @brief Checks if a MDMA channel id is within the valid range. + * + * @param[in] id MDMA channel id + * @retval The check result. + * @retval false invalid MDMA channel. + * @retval true correct MDMA channel. + */ +#define STM32_MDMA_IS_VALID_CHANNEL(id) (((id) >= 0U) && \ + ((id) <= STM32_MDMA_CHANNELS)) + +/** + * @brief Special stream identifier + */ +#define STM32_MDMA_CHANNEL_ID_ANY STM32_MDMA_CHANNELS + +/** + * @name CISR register constants + * @{ + */ +#define STM32_MDMA_CISR_TEIF (1U << 0) +#define STM32_MDMA_CISR_CTCIF (1U << 1) +#define STM32_MDMA_CISR_BRTIF (1U << 2) +#define STM32_MDMA_CISR_BTIF (1U << 3) +#define STM32_MDMA_CISR_TCIF (1U << 4) +#define STM32_MDMA_CISR_CRQA (1U << 16) +/** @} */ + +/** + * @name CIFCR register constants + * @{ + */ +#define STM32_MDMA_CIFCR_CTEIF (1U << 0) +#define STM32_MDMA_CIFCR_CCTCIF (1U << 1) +#define STM32_MDMA_CIFCR_CBRTIF (1U << 2) +#define STM32_MDMA_CIFCR_CBTIF (1U << 3) +#define STM32_MDMA_CIFCR_CTCIF (1U << 4) +/** @} */ + +/** + * @name CESR register constants + * @{ + */ +#define STM32_MDMA_CESR_TEA_MASK (127U << 0) +#define STM32_MDMA_CESR_TED (1U << 7) +#define STM32_MDMA_CESR_TELD (1U << 8) +#define STM32_MDMA_CESR_TEMD (1U << 9) +#define STM32_MDMA_CESR_ASE (1U << 10) +#define STM32_MDMA_CESR_BSE (1U << 11) +/** @} */ + +/** + * @name CCR register constants + * @{ + */ +#define STM32_MDMA_CCR_RESET_VALUE 0x00000000U +#define STM32_MDMA_CCR_EN (1U << 0) +#define STM32_MDMA_CCR_TEIE (1U << 1) +#define STM32_MDMA_CCR_CTCIE (1U << 2) +#define STM32_MDMA_CCR_BRTIE (1U << 3) +#define STM32_MDMA_CCR_BTIE (1U << 4) +#define STM32_MDMA_CCR_TCIE (1U << 5) +#define STM32_MDMA_CCR_PL_MASK (3U << 6) +#define STM32_MDMA_CCR_PL(n) ((n) << 6) +#define STM32_MDMA_CCR_BEX (1U << 12) +#define STM32_MDMA_CCR_HEX (1U << 13) +#define STM32_MDMA_CCR_WEX (1U << 14) +#define STM32_MDMA_CCR_SWRQ (1U << 16) +/** @} */ + +/** + * @name CTCR register constants + * @{ + */ +#define STM32_MDMA_CTCR_RESET_VALUE 0x00000000U + +#define STM32_MDMA_CTCR_SINC_MASK (3U << 0) +#define STM32_MDMA_CTCR_SINC(n) ((n) << 0) +#define STM32_MDMA_CTCR_SINC_FIXED STM32_MDMA_CTCR_SINC(0U) +#define STM32_MDMA_CTCR_SINC_INC STM32_MDMA_CTCR_SINC(2U) +#define STM32_MDMA_CTCR_SINC_DEC STM32_MDMA_CTCR_SINC(3U) + +#define STM32_MDMA_CTCR_DINC_MASK (3U << 2) +#define STM32_MDMA_CTCR_DINC(n) ((n) << 2) +#define STM32_MDMA_CTCR_DINC_FIXED STM32_MDMA_CTCR_DINC(0U) +#define STM32_MDMA_CTCR_DINC_INC STM32_MDMA_CTCR_DINC(2U) +#define STM32_MDMA_CTCR_DINC_DEC STM32_MDMA_CTCR_DINC(3U) + +#define STM32_MDMA_CTCR_SSIZE_MASK (3U << 4) +#define STM32_MDMA_CTCR_SSIZE(n) ((n) << 4) +#define STM32_MDMA_CTCR_SSIZE_BYTE STM32_MDMA_CTCR_SSIZE(0U) +#define STM32_MDMA_CTCR_SSIZE_HALF STM32_MDMA_CTCR_SSIZE(1U) +#define STM32_MDMA_CTCR_SSIZE_WORD STM32_MDMA_CTCR_SSIZE(2U) +#define STM32_MDMA_CTCR_SSIZE_DWORD STM32_MDMA_CTCR_SSIZE(3U) + +#define STM32_MDMA_CTCR_DSIZE_MASK (3U << 6) +#define STM32_MDMA_CTCR_DSIZE(n) ((n) << 6) +#define STM32_MDMA_CTCR_DSIZE_BYTE STM32_MDMA_CTCR_DSIZE(0U) +#define STM32_MDMA_CTCR_DSIZE_HALF STM32_MDMA_CTCR_DSIZE(1U) +#define STM32_MDMA_CTCR_DSIZE_WORD STM32_MDMA_CTCR_DSIZE(2U) +#define STM32_MDMA_CTCR_DSIZE_DWORD STM32_MDMA_CTCR_DSIZE(3U) + +#define STM32_MDMA_CTCR_SINCOS_MASK (3U << 8) +#define STM32_MDMA_CTCR_SINCOS(n) ((n) << 8) +#define STM32_MDMA_CTCR_SINCOS_BYTE STM32_MDMA_CTCR_SINCOS(0U) +#define STM32_MDMA_CTCR_SINCOS_HALF STM32_MDMA_CTCR_SINCOS(1U) +#define STM32_MDMA_CTCR_SINCOS_WORD STM32_MDMA_CTCR_SINCOS(2U) +#define STM32_MDMA_CTCR_SINCOS_DWORD STM32_MDMA_CTCR_SINCOS(3U) + +#define STM32_MDMA_CTCR_DINCOS_MASK (3U << 10) +#define STM32_MDMA_CTCR_DINCOS(n) ((n) << 10) +#define STM32_MDMA_CTCR_DINCOS_BYTE STM32_MDMA_CTCR_DINCOS(0U) +#define STM32_MDMA_CTCR_DINCOS_HALF STM32_MDMA_CTCR_DINCOS(1U) +#define STM32_MDMA_CTCR_DINCOS_WORD STM32_MDMA_CTCR_DINCOS(2U) +#define STM32_MDMA_CTCR_DINCOS_DWORD STM32_MDMA_CTCR_DINCOS(3U) + +#define STM32_MDMA_CTCR_SBURST_MASK (7U << 12) +#define STM32_MDMA_CTCR_SBURST(n) ((n) << 12) +#define STM32_MDMA_CTCR_SBURST_1 STM32_MDMA_CTCR_SBURST(0U) +#define STM32_MDMA_CTCR_SBURST_2 STM32_MDMA_CTCR_SBURST(1U) +#define STM32_MDMA_CTCR_SBURST_4 STM32_MDMA_CTCR_SBURST(2U) +#define STM32_MDMA_CTCR_SBURST_8 STM32_MDMA_CTCR_SBURST(3U) +#define STM32_MDMA_CTCR_SBURST_16 STM32_MDMA_CTCR_SBURST(4U) +#define STM32_MDMA_CTCR_SBURST_32 STM32_MDMA_CTCR_SBURST(5U) +#define STM32_MDMA_CTCR_SBURST_64 STM32_MDMA_CTCR_SBURST(6U) +#define STM32_MDMA_CTCR_SBURST_128 STM32_MDMA_CTCR_SBURST(7U) + +#define STM32_MDMA_CTCR_DBURST_MASK (7U << 15) +#define STM32_MDMA_CTCR_DBURST(n) ((n) << 15) +#define STM32_MDMA_CTCR_DBURST_1 STM32_MDMA_CTCR_DBURST(0U) +#define STM32_MDMA_CTCR_DBURST_2 STM32_MDMA_CTCR_DBURST(1U) +#define STM32_MDMA_CTCR_DBURST_4 STM32_MDMA_CTCR_DBURST(2U) +#define STM32_MDMA_CTCR_DBURST_8 STM32_MDMA_CTCR_DBURST(3U) +#define STM32_MDMA_CTCR_DBURST_16 STM32_MDMA_CTCR_DBURST(4U) +#define STM32_MDMA_CTCR_DBURST_32 STM32_MDMA_CTCR_DBURST(5U) +#define STM32_MDMA_CTCR_DBURST_64 STM32_MDMA_CTCR_DBURST(6U) +#define STM32_MDMA_CTCR_DBURST_128 STM32_MDMA_CTCR_DBURST(7U) + +#define STM32_MDMA_CTCR_TLEN_MASK (127U << 18) +#define STM32_MDMA_CTCR_TLEN(n) ((n) << 18) + +#define STM32_MDMA_CTCR_PKE (1U << 25) + +#define STM32_MDMA_CTCR_PAM_MASK (3U << 26) +#define STM32_MDMA_CTCR_PAM(n) ((n) << 26) +#define STM32_MDMA_CTCR_PAM_RIGHT STM32_MDMA_CTCR_PAM(0U) +#define STM32_MDMA_CTCR_PAM_RIGHT_SE STM32_MDMA_CTCR_PAM(1U) +#define STM32_MDMA_CTCR_PAM_LEFT STM32_MDMA_CTCR_PAM(2U) + +#define STM32_MDMA_CTCR_TRGM_MASK (3U << 28) +#define STM32_MDMA_CTCR_TRGM(n) ((n) << 28) +#define STM32_MDMA_CTCR_TRGM_BUFFER STM32_MDMA_CTCR_TRGM(0U) +#define STM32_MDMA_CTCR_TRGM_BLOCK STM32_MDMA_CTCR_TRGM(1U) +#define STM32_MDMA_CTCR_TRGM_REP_BLOCK STM32_MDMA_CTCR_TRGM(2U) +#define STM32_MDMA_CTCR_TRGM_WHOLE STM32_MDMA_CTCR_TRGM(3U) + +#define STM32_MDMA_CTCR_SWRM (1U << 30) + +#define STM32_MDMA_CTCR_BWM_MASK (1U << 31) +#define STM32_MDMA_CTCR_BWM_NON_BUFF (0U << 31) +#define STM32_MDMA_CTCR_BWM_BUFF (1U << 31) +/** @} */ + +/** + * @name BNDTR register constants + * @{ + */ +#define STM32_MDMA_CBNDTR_BNDT_MASK (0x1FFFFU << 0) +#define STM32_MDMA_CBNDTR_BNDT(n) ((n) << 0) +#define STM32_MDMA_CBNDTR_BRSUM (1U << 18) +#define STM32_MDMA_CBNDTR_BRDUM (1U << 19) +#define STM32_MDMA_CBNDTR_BRC_MASK (0xFFFU << 20) +#define STM32_MDMA_CBNDTR_BRC(n) ((n) << 20) +/** @} */ + +/** + * @name CBRUR register constants + * @{ + */ +#define STM32_MDMA_CBRUR_SUV_MASK (0xFFFFU << 0) +#define STM32_MDMA_CBRUR_SUV(n) ((n) << 0) +#define STM32_MDMA_CBRUR_DUV_MASK (0xFFFFU << 16) +#define STM32_MDMA_CBRUR_DUV(n) ((n) << 16) +/** @} */ + +/** + * @name CTBR register constants + * @{ + */ +#define STM32_MDMA_CTBR_TSEL_MASK (0x3FU << 0) +#define STM32_MDMA_CTBR_TSEL(n) ((n) << 0) +#define STM32_MDMA_CTBR_TSEL_SBUS (1U << 16) +#define STM32_MDMA_CTBR_TSEL_DBUS (1U << 17) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_MDMA_HANDLER) +#error "STM32_MDMA_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_NUMBER) +#error "STM32_MDMA_NUMBER missing in registry" +#endif + +/* Priority settings checks.*/ +#if !defined(STM32_IRQ_MDMA_PRIORITY) +#error "STM32_IRQ_MDMA_PRIORITY not defined in mcuconf.h" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_MDMA_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_MDMA_PRIORITY" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 MDMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags content of the CISR register + */ +typedef void (*stm32_mdmaisr_t)(void *p, uint32_t flags); + +/** + * @brief STM32 MDMA stream descriptor structure. + */ +typedef struct { + /** + * @brief Associated MDMA channel. + */ + MDMA_Channel_TypeDef *channel; + /** + * @brief MDMA callback function. + */ + stm32_mdmaisr_t func; + /** + * @brief MDMA callback parameter. + */ + void *param; +} stm32_mdma_channel_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Associates a source address to a MDMA stream. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] addr value to be written in the CSAR register + * + * @xclass + */ +#define mdmaChannelSetSourceX(mdmachp, addr) do { \ + (mdmachp)->channel->CSAR = (uint32_t)(addr); \ +} while (0) + +/** + * @brief Associates a memory destination to a MDMA stream. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] addr value to be written in the CDAR register + * + * @xclass + */ +#define mdmaChannelSetDestinationX(mdmachp, addr) do { \ + (mdmachp)->channel->CDAR = (uint32_t)(addr); \ +} while (0) + +/** + * @brief Sets parameters related to the transaction size. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] size number of bytes per block + * @param[in] n number of blocks repetitions + * @param[in] opt other option bits for the CBNDTR register + * + * @xclass + */ +#define mdmaChannelSetTransactionSizeX(mdmachp, size, n, opt) do { \ + (mdmachp)->channel->CBNDTR = (uint32_t)STM32_MDMA_CBNDTR_BNDT(size) | \ + (uint32_t)STM32_MDMA_CBNDTR_BRC(n) | \ + (uint32_t)opt; \ +} while (0) + +/** + * @brief Programs the stream mode settings. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] ctcr value to be written in the CTCR register + * @param[in] ccr value to be written in the CCR register + * + * @xclass + */ +#define mdmaChannelSetModeX(mdmachp, ctcr, ccr) do { \ + (mdmachp)->channel->CTCR = (uint32_t)(ctcr); \ + (mdmachp)->channel->CCR = (uint32_t)(ccr); \ +} while (0) + +/** + * @brief Programs the trigger mode settings. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] tsel value to be written in the CTBR register + * + * @xclass + */ +#define mdmaChannelSetTrigModeX(mdmachp, tsel) do { \ + (mdmachp)->channel->CTBR = STM32_MDMA_CTBR_TSEL(tsel); \ +} while (0) + +/** + * @brief MDMA stream enable. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @xclass + */ +#define mdmaChannelEnableX(mdmachp) do { \ + (mdmachp)->channel->CCR |= STM32_MDMA_CCR_EN; \ +} while (0) + +/** + * @brief Channel enable check. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + */ +#define mdmaChannelIsEnabled(mdmachp) \ + (((mdmachp)->channel->CCR & STM32_MDMA_CCR_EN) != 0U) + +/** + * @brief MDMA stream interrupt sources clear. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @xclass + */ +#define mdmaChannelClearInterruptX(mdmachp) do { \ + (mdmachp)->channel->CIFCR = (STM32_MDMA_CIFCR_CTEIF | \ + STM32_MDMA_CIFCR_CBRTIF | \ + STM32_MDMA_CIFCR_CBRTIF | \ + STM32_MDMA_CIFCR_CCTCIF | \ + STM32_MDMA_CIFCR_CTEIF); \ +} while (0) + +/** + * @brief MDMA IRQ enable. + */ +#define mdma_irq_init() \ + nvicEnableVector(STM32_MDMA_NUMBER, STM32_IRQ_MDMA_PRIORITY) + +/** + * @brief MDMA IRQ disable. + */ +#define mdma_irq_deinit() \ + nvicDisableVector(STM32_MDMA_NUMBER) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void mdmaInit(void); + const stm32_mdma_channel_t *mdmaChannelAllocI(uint32_t id, + stm32_mdmaisr_t func, + void *param); + const stm32_mdma_channel_t *mdmaChannelAlloc(uint32_t id, + stm32_mdmaisr_t func, + void *param); + void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp); + void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp); + void mdmaChannelDisableX(const stm32_mdma_channel_t *mdmachp); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_MDMA_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk b/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk index 987220b5a4..527bf5469c 100644 --- a/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk +++ b/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1 diff --git a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c index 4b78488ddf..a91284ccb7 100644 --- a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c +++ b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c @@ -1,470 +1,470 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file OCTOSPIv1/hal_wspi_lld.c - * @brief STM32 WSPI subsystem low level driver source. - * - * @addtogroup WSPI - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* Workarounds for bugs in ST headers.*/ -#if !defined(OCTOSPI_FCR_CTOF) && defined(OCTOSPI_FCR_TOF) -#define OCTOSPI_FCR_CTOF OCTOSPI_FCR_TOF -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief OCTOSPI1 driver identifier.*/ -#if STM32_WSPI_USE_OCTOSPI1 || defined(__DOXYGEN__) -WSPIDriver WSPID1; -#endif - -/** @brief OCTOSPI2 driver identifier.*/ -#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__) -WSPIDriver WSPID2; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Waits for completion of previous operation. - */ -static inline void wspi_lld_sync(WSPIDriver *wspip) { - - while ((wspip->ospi->SR & OCTOSPI_SR_BUSY) != 0U) { - } -} - -/** - * @brief Shared service routine. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void wspi_lld_serve_dma_interrupt(WSPIDriver *wspip, uint32_t flags) { - - (void)wspip; - (void)flags; - - /* DMA errors handling.*/ -#if defined(STM32_WSPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_WSPI_DMA_ERROR_HOOK(wspip); - } -#endif -} - -/** - * @brief Shared service routine. - * - * @param[in] wspip pointer to the @p WSPIDriver object - */ -static void wspi_lld_serve_interrupt(WSPIDriver *wspip) { - - /* Portable WSPI ISR code defined in the high level driver, note, it is - a macro.*/ - _wspi_isr_code(wspip); - - /* Stop everything, we need to give DMA enough time to complete the ongoing - operation. Race condition hidden here.*/ - while (dmaStreamGetTransactionSize(wspip->dma) > 0U) - ; - dmaStreamDisable(wspip->dma); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_WSPI_USE_OCTOSPI1 || defined(__DOXYGEN__) -#if !defined(STM32_OCTOSPI1_SUPPRESS_ISR) -#if !defined(STM32_OCTOSPI1_HANDLER) -#error "STM32_OCTOSPI1_HANDLER not defined" -#endif -/** - * @brief STM32_OCTOSPI1_HANDLER interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_OCTOSPI1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - OCTOSPI1->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | - OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; - - wspi_lld_serve_interrupt(&WSPID1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_OCTOSPI1_SUPPRESS_ISR) */ -#endif /* STM32_WSPI_USE_OCTOSPI1 */ - -#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__) -#if !defined(STM32_OCTOSPI2_SUPPRESS_ISR) -#if !defined(STM32_OCTOSPI2_HANDLER) -#error "STM32_OCTOSPI2_HANDLER not defined" -#endif -/** - * @brief STM32_OCTOSPI2_HANDLER interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_OCTOSPI2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - OCTOSPI2->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | - OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; - - wspi_lld_serve_interrupt(&WSPID2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_OCTOSPI2_SUPPRESS_ISR) */ -#endif /* STM32_WSPI_USE_OCTOSPI2 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level WSPI driver initialization. - * - * @notapi - */ -void wspi_lld_init(void) { - -#if STM32_WSPI_USE_OCTOSPI1 - wspiObjectInit(&WSPID1); - WSPID1.ospi = OCTOSPI1; - WSPID1.dma = NULL; - WSPID1.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI1_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_BYTE | - STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - nvicEnableVector(STM32_OCTOSPI1_NUMBER, STM32_WSPI_OCTOSPI1_IRQ_PRIORITY); -#endif - -#if STM32_WSPI_USE_OCTOSPI2 - wspiObjectInit(&WSPID2); - WSPID2.ospi = OCTOSPI2; - WSPID2.dma = NULL; - WSPID2.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI2_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_BYTE | - STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - nvicEnableVector(STM32_OCTOSPI2_NUMBER, STM32_WSPI_OCTOSPI2_IRQ_PRIORITY); -#endif -} - -/** - * @brief Configures and activates the WSPI peripheral. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_start(WSPIDriver *wspip) { - - /* If in stopped state then full initialization.*/ - if (wspip->state == WSPI_STOP) { -#if STM32_WSPI_USE_OCTOSPI1 - if (&WSPID1 == wspip) { - wspip->dma = dmaStreamAllocI(STM32_WSPI_OCTOSPI1_DMA_STREAM, - STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, - (void *)wspip); - osalDbgAssert(wspip->dma != NULL, "unable to allocate stream"); - rccEnableOCTOSPI1(true); - dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_OCTOSPI1); - } -#endif - -#if STM32_WSPI_USE_OCTOSPI2 - if (&WSPID2 == wspip) { - wspip->dma = dmaStreamAllocI(STM32_WSPI_OCTOSPI2_DMA_STREAM, - STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, - (void *)wspip); - osalDbgAssert(wspip->dma != NULL, "unable to allocate stream"); - rccEnableOCTOSPI2(true); - dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_OCTOSPI2); - } -#endif - - /* Common initializations.*/ - dmaStreamSetPeripheral(wspip->dma, &wspip->ospi->DR); - } - - /* WSPI setup and enable.*/ - wspip->ospi->DCR1 = wspip->config->dcr1; - wspip->ospi->DCR2 = wspip->config->dcr2 | - STM32_DCR2_PRESCALER(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE - 1U); - wspip->ospi->DCR3 = wspip->config->dcr3; - wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN; - wspip->ospi->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | - OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; -} - -/** - * @brief Deactivates the WSPI peripheral. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_stop(WSPIDriver *wspip) { - - /* Waiting for the previous operation to complete, if any.*/ - wspi_lld_sync(wspip); - - /* If in ready state then disables the OCTOSPI clock.*/ - if (wspip->state == WSPI_READY) { - - /* WSPI disable.*/ - wspip->ospi->CR = 0U; - - /* Releasing the DMA.*/ - dmaStreamFreeI(wspip->dma); - wspip->dma = NULL; - - /* Stopping involved clocks.*/ -#if STM32_WSPI_USE_OCTOSPI1 - if (&WSPID1 == wspip) { - rccDisableOCTOSPI1(); - } -#endif - -#if STM32_WSPI_USE_OCTOSPI2 - if (&WSPID2 == wspip) { - rccDisableOCTOSPI2(); - } -#endif - } -} - -/** - * @brief Sends a command without data phase. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * - * @notapi - */ -void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { - -#if 0 //STM32_USE_STM32_D1_WORKAROUND == TRUE - /* If it is a command without address and alternate phases then the command - is sent as an alternate byte, the command phase is suppressed.*/ - if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { - /* The command mode field is copied in the alternate mode field. All - other fields are not used in this scenario.*/ - wspip->ospi->DLR = 0U; - wspip->ospi->ABR = cmdp->cmd; - wspip->ospi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U; - return; - } -#endif - wspip->ospi->CR &= ~OCTOSPI_CR_FMODE; - wspip->ospi->DLR = 0U; - wspip->ospi->TCR = cmdp->dummy; - wspip->ospi->CCR = cmdp->cfg; - wspip->ospi->ABR = cmdp->alt; - wspip->ospi->IR = cmdp->cmd; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->ospi->AR = cmdp->addr; - } - - /* Waiting for the previous operation to complete.*/ - wspi_lld_sync(wspip); -} - -/** - * @brief Sends a command with data over the WSPI bus. - * @post At the end of the operation the configured callback is invoked. - * @note If using DTR in 8 lines mode then the following restrictions - * apply: - * - Command size must be 0, 2 or 4 bytes. - * - Address must be even. - * - Alternate bytes size must be 0, 2 or 4 bytes. - * - Data size must be a multiple of two. - * . - * There is no check on the above conditions in order to keep the - * code efficient. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[in] n number of bytes to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, const uint8_t *txbuf) { - - dmaStreamSetMemory0(wspip->dma, txbuf); - dmaStreamSetTransactionSize(wspip->dma, n); - dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P); - - wspip->ospi->CR &= ~OCTOSPI_CR_FMODE; - wspip->ospi->DLR = n - 1U; - wspip->ospi->TCR = cmdp->dummy; - wspip->ospi->CCR = cmdp->cfg; - wspip->ospi->ABR = cmdp->alt; - wspip->ospi->IR = cmdp->cmd; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->ospi->AR = cmdp->addr; - } - - dmaStreamEnable(wspip->dma); -} - -/** - * @brief Sends a command then receives data over the WSPI bus. - * @post At the end of the operation the configured callback is invoked. - * @note If using DTR in 8 lines mode then the following restrictions - * apply: - * - Command size must be 0, 2 or 4 bytes. - * - Address must be even. - * - Alternate bytes size must be 0, 2 or 4 bytes. - * - Data size must be a multiple of two. - * . - * There is no check on the above conditions in order to keep the - * code efficient. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[in] n number of bytes to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, uint8_t *rxbuf) { - - dmaStreamSetMemory0(wspip->dma, rxbuf); - dmaStreamSetTransactionSize(wspip->dma, n); - dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M); - - wspip->ospi->CR = (wspip->ospi->CR & ~OCTOSPI_CR_FMODE) | OCTOSPI_CR_FMODE_0; - wspip->ospi->DLR = n - 1U; - wspip->ospi->TCR = cmdp->dummy; - wspip->ospi->CCR = cmdp->cfg; - wspip->ospi->ABR = cmdp->alt; - wspip->ospi->IR = cmdp->cmd; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->ospi->AR = cmdp->addr; - } - - dmaStreamEnable(wspip->dma); -} - -#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) -/** - * @brief Maps in memory space a WSPI flash device. - * @pre The memory flash device must be initialized appropriately - * before mapping it in memory space. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[out] addrp pointer to the memory start address of the mapped - * flash or @p NULL - * - * @notapi - */ -void wspi_lld_map_flash(WSPIDriver *wspip, - const wspi_command_t *cmdp, - uint8_t **addrp) { - - /* Starting memory mapped mode using the passed parameters.*/ - wspip->ospi->CR = OCTOSPI_CR_FMODE_1 | OCTOSPI_CR_FMODE_0 | OCTOSPI_CR_EN; - wspip->ospi->TCR = cmdp->dummy; - wspip->ospi->CCR = cmdp->cfg; - wspip->ospi->IR = cmdp->cmd; - wspip->ospi->ABR = 0U; - wspip->ospi->AR = 0U; - wspip->ospi->WTCR = 0U; - wspip->ospi->WCCR = 0U; - wspip->ospi->WIR = 0U; - wspip->ospi->WABR = 0U; - - /* Mapped flash absolute base address.*/ -#if STM32_WSPI_USE_OCTOSPI1 - if (&WSPID1 == wspip) { - if (addrp != NULL) { - *addrp = (uint8_t *)0x90000000U; - } - } -#endif -#if STM32_WSPI_USE_OCTOSPI2 - if (&WSPID2 == wspip) { - if (addrp != NULL) { - *addrp = (uint8_t *)0x70000000U; - } - } -#endif -} - -/** - * @brief Unmaps from memory space a WSPI flash device. - * @post The memory flash device must be re-initialized for normal - * commands exchange. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_unmap_flash(WSPIDriver *wspip) { - - /* Aborting memory mapped mode.*/ - wspip->ospi->CR |= OCTOSPI_CR_ABORT; - while ((wspip->ospi->CR & OCTOSPI_CR_ABORT) != 0U) { - } - - /* Disabling memory mapped mode and re-enabling DMA and IRQs.*/ - wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN; -} -#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ - -#endif /* HAL_USE_WSPI */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file OCTOSPIv1/hal_wspi_lld.c + * @brief STM32 WSPI subsystem low level driver source. + * + * @addtogroup WSPI + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* Workarounds for bugs in ST headers.*/ +#if !defined(OCTOSPI_FCR_CTOF) && defined(OCTOSPI_FCR_TOF) +#define OCTOSPI_FCR_CTOF OCTOSPI_FCR_TOF +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief OCTOSPI1 driver identifier.*/ +#if STM32_WSPI_USE_OCTOSPI1 || defined(__DOXYGEN__) +WSPIDriver WSPID1; +#endif + +/** @brief OCTOSPI2 driver identifier.*/ +#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__) +WSPIDriver WSPID2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Waits for completion of previous operation. + */ +static inline void wspi_lld_sync(WSPIDriver *wspip) { + + while ((wspip->ospi->SR & OCTOSPI_SR_BUSY) != 0U) { + } +} + +/** + * @brief Shared service routine. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void wspi_lld_serve_dma_interrupt(WSPIDriver *wspip, uint32_t flags) { + + (void)wspip; + (void)flags; + + /* DMA errors handling.*/ +#if defined(STM32_WSPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_WSPI_DMA_ERROR_HOOK(wspip); + } +#endif +} + +/** + * @brief Shared service routine. + * + * @param[in] wspip pointer to the @p WSPIDriver object + */ +static void wspi_lld_serve_interrupt(WSPIDriver *wspip) { + + /* Portable WSPI ISR code defined in the high level driver, note, it is + a macro.*/ + _wspi_isr_code(wspip); + + /* Stop everything, we need to give DMA enough time to complete the ongoing + operation. Race condition hidden here.*/ + while (dmaStreamGetTransactionSize(wspip->dma) > 0U) + ; + dmaStreamDisable(wspip->dma); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_WSPI_USE_OCTOSPI1 || defined(__DOXYGEN__) +#if !defined(STM32_OCTOSPI1_SUPPRESS_ISR) +#if !defined(STM32_OCTOSPI1_HANDLER) +#error "STM32_OCTOSPI1_HANDLER not defined" +#endif +/** + * @brief STM32_OCTOSPI1_HANDLER interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_OCTOSPI1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + OCTOSPI1->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | + OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; + + wspi_lld_serve_interrupt(&WSPID1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_OCTOSPI1_SUPPRESS_ISR) */ +#endif /* STM32_WSPI_USE_OCTOSPI1 */ + +#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__) +#if !defined(STM32_OCTOSPI2_SUPPRESS_ISR) +#if !defined(STM32_OCTOSPI2_HANDLER) +#error "STM32_OCTOSPI2_HANDLER not defined" +#endif +/** + * @brief STM32_OCTOSPI2_HANDLER interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_OCTOSPI2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + OCTOSPI2->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | + OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; + + wspi_lld_serve_interrupt(&WSPID2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_OCTOSPI2_SUPPRESS_ISR) */ +#endif /* STM32_WSPI_USE_OCTOSPI2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level WSPI driver initialization. + * + * @notapi + */ +void wspi_lld_init(void) { + +#if STM32_WSPI_USE_OCTOSPI1 + wspiObjectInit(&WSPID1); + WSPID1.ospi = OCTOSPI1; + WSPID1.dma = NULL; + WSPID1.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI1_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_BYTE | + STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + nvicEnableVector(STM32_OCTOSPI1_NUMBER, STM32_WSPI_OCTOSPI1_IRQ_PRIORITY); +#endif + +#if STM32_WSPI_USE_OCTOSPI2 + wspiObjectInit(&WSPID2); + WSPID2.ospi = OCTOSPI2; + WSPID2.dma = NULL; + WSPID2.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI2_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_BYTE | + STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + nvicEnableVector(STM32_OCTOSPI2_NUMBER, STM32_WSPI_OCTOSPI2_IRQ_PRIORITY); +#endif +} + +/** + * @brief Configures and activates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_start(WSPIDriver *wspip) { + + /* If in stopped state then full initialization.*/ + if (wspip->state == WSPI_STOP) { +#if STM32_WSPI_USE_OCTOSPI1 + if (&WSPID1 == wspip) { + wspip->dma = dmaStreamAllocI(STM32_WSPI_OCTOSPI1_DMA_STREAM, + STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, + (void *)wspip); + osalDbgAssert(wspip->dma != NULL, "unable to allocate stream"); + rccEnableOCTOSPI1(true); + dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_OCTOSPI1); + } +#endif + +#if STM32_WSPI_USE_OCTOSPI2 + if (&WSPID2 == wspip) { + wspip->dma = dmaStreamAllocI(STM32_WSPI_OCTOSPI2_DMA_STREAM, + STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, + (void *)wspip); + osalDbgAssert(wspip->dma != NULL, "unable to allocate stream"); + rccEnableOCTOSPI2(true); + dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_OCTOSPI2); + } +#endif + + /* Common initializations.*/ + dmaStreamSetPeripheral(wspip->dma, &wspip->ospi->DR); + } + + /* WSPI setup and enable.*/ + wspip->ospi->DCR1 = wspip->config->dcr1; + wspip->ospi->DCR2 = wspip->config->dcr2 | + STM32_DCR2_PRESCALER(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE - 1U); + wspip->ospi->DCR3 = wspip->config->dcr3; + wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN; + wspip->ospi->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF | + OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF; +} + +/** + * @brief Deactivates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_stop(WSPIDriver *wspip) { + + /* Waiting for the previous operation to complete, if any.*/ + wspi_lld_sync(wspip); + + /* If in ready state then disables the OCTOSPI clock.*/ + if (wspip->state == WSPI_READY) { + + /* WSPI disable.*/ + wspip->ospi->CR = 0U; + + /* Releasing the DMA.*/ + dmaStreamFreeI(wspip->dma); + wspip->dma = NULL; + + /* Stopping involved clocks.*/ +#if STM32_WSPI_USE_OCTOSPI1 + if (&WSPID1 == wspip) { + rccDisableOCTOSPI1(); + } +#endif + +#if STM32_WSPI_USE_OCTOSPI2 + if (&WSPID2 == wspip) { + rccDisableOCTOSPI2(); + } +#endif + } +} + +/** + * @brief Sends a command without data phase. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * + * @notapi + */ +void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { + +#if 0 //STM32_USE_STM32_D1_WORKAROUND == TRUE + /* If it is a command without address and alternate phases then the command + is sent as an alternate byte, the command phase is suppressed.*/ + if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { + /* The command mode field is copied in the alternate mode field. All + other fields are not used in this scenario.*/ + wspip->ospi->DLR = 0U; + wspip->ospi->ABR = cmdp->cmd; + wspip->ospi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U; + return; + } +#endif + wspip->ospi->CR &= ~OCTOSPI_CR_FMODE; + wspip->ospi->DLR = 0U; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; + wspip->ospi->ABR = cmdp->alt; + wspip->ospi->IR = cmdp->cmd; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->ospi->AR = cmdp->addr; + } + + /* Waiting for the previous operation to complete.*/ + wspi_lld_sync(wspip); +} + +/** + * @brief Sends a command with data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * @note If using DTR in 8 lines mode then the following restrictions + * apply: + * - Command size must be 0, 2 or 4 bytes. + * - Address must be even. + * - Alternate bytes size must be 0, 2 or 4 bytes. + * - Data size must be a multiple of two. + * . + * There is no check on the above conditions in order to keep the + * code efficient. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf) { + + dmaStreamSetMemory0(wspip->dma, txbuf); + dmaStreamSetTransactionSize(wspip->dma, n); + dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P); + + wspip->ospi->CR &= ~OCTOSPI_CR_FMODE; + wspip->ospi->DLR = n - 1U; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; + wspip->ospi->ABR = cmdp->alt; + wspip->ospi->IR = cmdp->cmd; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->ospi->AR = cmdp->addr; + } + + dmaStreamEnable(wspip->dma); +} + +/** + * @brief Sends a command then receives data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * @note If using DTR in 8 lines mode then the following restrictions + * apply: + * - Command size must be 0, 2 or 4 bytes. + * - Address must be even. + * - Alternate bytes size must be 0, 2 or 4 bytes. + * - Data size must be a multiple of two. + * . + * There is no check on the above conditions in order to keep the + * code efficient. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf) { + + dmaStreamSetMemory0(wspip->dma, rxbuf); + dmaStreamSetTransactionSize(wspip->dma, n); + dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M); + + wspip->ospi->CR = (wspip->ospi->CR & ~OCTOSPI_CR_FMODE) | OCTOSPI_CR_FMODE_0; + wspip->ospi->DLR = n - 1U; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; + wspip->ospi->ABR = cmdp->alt; + wspip->ospi->IR = cmdp->cmd; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->ospi->AR = cmdp->addr; + } + + dmaStreamEnable(wspip->dma); +} + +#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a WSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @notapi + */ +void wspi_lld_map_flash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp) { + + /* Starting memory mapped mode using the passed parameters.*/ + wspip->ospi->CR = OCTOSPI_CR_FMODE_1 | OCTOSPI_CR_FMODE_0 | OCTOSPI_CR_EN; + wspip->ospi->TCR = cmdp->dummy; + wspip->ospi->CCR = cmdp->cfg; + wspip->ospi->IR = cmdp->cmd; + wspip->ospi->ABR = 0U; + wspip->ospi->AR = 0U; + wspip->ospi->WTCR = 0U; + wspip->ospi->WCCR = 0U; + wspip->ospi->WIR = 0U; + wspip->ospi->WABR = 0U; + + /* Mapped flash absolute base address.*/ +#if STM32_WSPI_USE_OCTOSPI1 + if (&WSPID1 == wspip) { + if (addrp != NULL) { + *addrp = (uint8_t *)0x90000000U; + } + } +#endif +#if STM32_WSPI_USE_OCTOSPI2 + if (&WSPID2 == wspip) { + if (addrp != NULL) { + *addrp = (uint8_t *)0x70000000U; + } + } +#endif +} + +/** + * @brief Unmaps from memory space a WSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_unmap_flash(WSPIDriver *wspip) { + + /* Aborting memory mapped mode.*/ + wspip->ospi->CR |= OCTOSPI_CR_ABORT; + while ((wspip->ospi->CR & OCTOSPI_CR_ABORT) != 0U) { + } + + /* Disabling memory mapped mode and re-enabling DMA and IRQs.*/ + wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN; +} +#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ + +#endif /* HAL_USE_WSPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h index 8d990814f6..e91c88ea9a 100644 --- a/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h +++ b/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h @@ -1,339 +1,339 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file OCTOSPIv1/hal_wspi_lld.h - * @brief STM32 WSPI subsystem low level driver header. - * - * @addtogroup WSPI - * @{ - */ - -#ifndef HAL_WSPI_LLD_H -#define HAL_WSPI_LLD_H - -#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name WSPI implementation capabilities - * @{ - */ -#define WSPI_SUPPORTS_MEMMAP TRUE -#define WSPI_DEFAULT_CFG_MASKS TRUE -/** @} */ - -/** - * @name DCR1 register options - * @{ - */ -#define STM32_DCR1_CK_MODE (1U << 0U) -#define STM32_DCR1_FRCK_MODE (1U << 1U) -#define STM32_DCR1_CSHT_MASK (7U << 8U) -#define STM32_DCR1_CSHT(n) ((n) << 8U) -#define STM32_DCR1_DEVSIZE_MASK (31U << 16U) -#define STM32_DCR1_DEVSIZE(n) ((n) << 16U) -#define STM32_DCR1_MTYP_MASK (7U << 16U) -#define STM32_DCR1_MTYP(n) ((n) << 24U) -/** @} */ - -/** - * @name DCR2 register options - * @{ - */ -#define STM32_DCR2_PRESCALER_MASK (255U << 0U) -#define STM32_DCR2_PRESCALER(n) ((n) << 0U) -#define STM32_DCR2_WRAPSIZE_MASK (7U << 16U) -#define STM32_DCR2_WRAPSIZE(n) ((n) << 16U) - -/** - * @name DCR3 register options - * @{ - */ -#define STM32_DCR3_MAXTRAN_MASK (255U << 0U) -#define STM32_DCR3_MAXTRAN(n) ((n) << 0U) -#define STM32_DCR3_CSBOUND_MASK (7U << 16U) -#define STM32_DCR3_CSBOUND(n) ((n) << 16U) - -/** - * @name DCR4 register options - * @{ - */ -#define STM32_DCR4_REFRESH_MASK (255U << 0U) -#define STM32_DCR4_REFRESH(n) ((n) << 0U) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief WSPID1 driver enable switch. - * @details If set to @p TRUE the support for OCTOSPI1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_WSPI_USE_OCTOSPI1) || defined(__DOXYGEN__) -#define STM32_WSPI_USE_OCTOSPI1 FALSE -#endif - -/** - * @brief WSPID2 driver enable switch. - * @details If set to @p TRUE the support for OCTOSPI2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_WSPI_USE_OCTOSPI2) || defined(__DOXYGEN__) -#define STM32_WSPI_USE_OCTOSPI2 FALSE -#endif - -/** - * @brief OCTOSPI1 prescaler setting. - * @note This is the prescaler divider value 1..256. The maximum frequency - * varies depending on the STM32 model and operating conditions, - * find the details in the data sheet. - */ -#if !defined(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI1_PRESCALER_VALUE 1 -#endif - -/** - * @brief OCTOSPI2 prescaler setting. - * @note This is the prescaler divider value 1..256. The maximum frequency - * varies depending on the STM32 model and operating conditions, - * find the details in the data sheet. - */ -#if !defined(STM32_WSPI_OCTOSPI2_PRESCALER_VALUE) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI2_PRESCALER_VALUE 1 -#endif - -/** - * @brief OCTOSPI1 interrupt priority level setting. - */ -#if !defined(STM32_WSPI_OCTOSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief OCTOSPI2 interrupt priority level setting. - */ -#if !defined(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief OCTOSPI1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief OCTOSPI2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief OCTOSPI1 DMA interrupt priority level setting. - */ -#if !defined(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY 10 -#endif - -/** - * @brief OCTOSPI2 DMA interrupt priority level setting. - */ -#if !defined(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY 10 -#endif - -/** - * @brief OCTOSPI DMA error hook. - */ -#if !defined(STM32_WSPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_WSPI_DMA_ERROR_HOOK(wspip) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_OCTOSPI1) -#define STM32_HAS_OCTOSPI1 FALSE -#endif - -#if !defined(STM32_HAS_OCTOSPI2) -#define STM32_HAS_OCTOSPI2 FALSE -#endif - -#if STM32_WSPI_USE_OCTOSPI1 && !STM32_HAS_OCTOSPI1 -#error "OCTOSPI1 not present in the selected device" -#endif - -#if STM32_WSPI_USE_OCTOSPI2 && !STM32_HAS_OCTOSPI2 -#error "OCTOSPI2 not present in the selected device" -#endif - -#if !STM32_WSPI_USE_OCTOSPI1 && !STM32_WSPI_USE_OCTOSPI2 -#error "WSPI driver activated but no OCTOSPI peripheral assigned" -#endif - -/* Check on OCTOSPI prescaler setting.*/ -#if (STM32_WSPI_OCTOSPI1_PRESCALER_VALUE < 1) || \ - (STM32_WSPI_OCTOSPI1_PRESCALER_VALUE > 256) -#error "STM32_WSPI_OCTOSPI1_PRESCALER_VALUE not within 1..256" -#endif - -#if (STM32_WSPI_OCTOSPI2_PRESCALER_VALUE < 1) || \ - (STM32_WSPI_OCTOSPI2_PRESCALER_VALUE > 256) -#error "STM32_WSPI_OCTOSPI2_PRESCALER_VALUE not within 1..256" -#endif - -/* Check on IRQ priorities.*/ -#if STM32_WSPI_USE_OCTOSPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OCTOSPI1" -#endif - -#if STM32_WSPI_USE_OCTOSPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OCTOSPI2" -#endif - -#if STM32_WSPI_USE_OCTOSPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OCTOSPI1 DMA" -#endif - -#if STM32_WSPI_USE_OCTOSPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OCTOSPI2 DMA" -#endif - -/* Check on the presence of the DMA channels settings in mcuconf.h.*/ -#if STM32_WSPI_USE_OCTOSPI1 && !defined(STM32_WSPI_OCTOSPI1_DMA_STREAM) -#error "OCTOSPI1 DMA stream not defined" -#endif - -#if STM32_WSPI_USE_OCTOSPI2 && !defined(STM32_WSPI_OCTOSPI2_DMA_STREAM) -#error "OCTOSPI2 DMA stream not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_WSPI_USE_OCTOSPI1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_OCTOSPI1_DMA_STREAM) -#error "invalid DMA stream associated to OCTOSPI1" -#endif - -#if STM32_WSPI_USE_OCTOSPI2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_OCTOSPI2_DMA_STREAM) -#error "invalid DMA stream associated to OCTOSPI2" -#endif - -/* Check on DMA channels priority.*/ -#if STM32_WSPI_USE_OCTOSPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to OCTOSPI1" -#endif - -#if STM32_WSPI_USE_OCTOSPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to OCTOSPI2" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the WSPI configuration structure. - */ -#define wspi_lld_config_fields \ - /* DCR1 register initialization data.*/ \ - uint32_t dcr1; \ - /* DCR2 register initialization data. The prescaler field is internally \ - ORed to this field, leave it to zero.*/ \ - uint32_t dcr2; \ - /* DCR3 register initialization data.*/ \ - uint32_t dcr3; \ - /* DCR4 register initialization data.*/ \ - uint32_t dcr4 - -/** - * @brief Low level fields of the WSPI driver structure. - */ -#define wspi_lld_driver_fields \ - /* Pointer to the OCTOSPIx registers block.*/ \ - OCTOSPI_TypeDef *ospi; \ - /* OCTOSPI DMA stream.*/ \ - const stm32_dma_stream_t *dma; \ - /* OCTOSPI DMA mode bit mask.*/ \ - uint32_t dmamode - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if (STM32_WSPI_USE_OCTOSPI1 == TRUE) && !defined(__DOXYGEN__) -extern WSPIDriver WSPID1; -#endif - -#if (STM32_WSPI_USE_OCTOSPI2 == TRUE) && !defined(__DOXYGEN__) -extern WSPIDriver WSPID2; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void wspi_lld_init(void); - void wspi_lld_start(WSPIDriver *wspip); - void wspi_lld_stop(WSPIDriver *wspip); - void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp); - void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, const uint8_t *txbuf); - void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, uint8_t *rxbuf); -#if WSPI_SUPPORTS_MEMMAP == TRUE - void wspi_lld_map_flash(WSPIDriver *wspip, - const wspi_command_t *cmdp, - uint8_t **addrp); - void wspi_lld_unmap_flash(WSPIDriver *wspip); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_WSPI */ - -#endif /* HAL_WSPI_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file OCTOSPIv1/hal_wspi_lld.h + * @brief STM32 WSPI subsystem low level driver header. + * + * @addtogroup WSPI + * @{ + */ + +#ifndef HAL_WSPI_LLD_H +#define HAL_WSPI_LLD_H + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name WSPI implementation capabilities + * @{ + */ +#define WSPI_SUPPORTS_MEMMAP TRUE +#define WSPI_DEFAULT_CFG_MASKS TRUE +/** @} */ + +/** + * @name DCR1 register options + * @{ + */ +#define STM32_DCR1_CK_MODE (1U << 0U) +#define STM32_DCR1_FRCK_MODE (1U << 1U) +#define STM32_DCR1_CSHT_MASK (7U << 8U) +#define STM32_DCR1_CSHT(n) ((n) << 8U) +#define STM32_DCR1_DEVSIZE_MASK (31U << 16U) +#define STM32_DCR1_DEVSIZE(n) ((n) << 16U) +#define STM32_DCR1_MTYP_MASK (7U << 16U) +#define STM32_DCR1_MTYP(n) ((n) << 24U) +/** @} */ + +/** + * @name DCR2 register options + * @{ + */ +#define STM32_DCR2_PRESCALER_MASK (255U << 0U) +#define STM32_DCR2_PRESCALER(n) ((n) << 0U) +#define STM32_DCR2_WRAPSIZE_MASK (7U << 16U) +#define STM32_DCR2_WRAPSIZE(n) ((n) << 16U) + +/** + * @name DCR3 register options + * @{ + */ +#define STM32_DCR3_MAXTRAN_MASK (255U << 0U) +#define STM32_DCR3_MAXTRAN(n) ((n) << 0U) +#define STM32_DCR3_CSBOUND_MASK (7U << 16U) +#define STM32_DCR3_CSBOUND(n) ((n) << 16U) + +/** + * @name DCR4 register options + * @{ + */ +#define STM32_DCR4_REFRESH_MASK (255U << 0U) +#define STM32_DCR4_REFRESH(n) ((n) << 0U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief WSPID1 driver enable switch. + * @details If set to @p TRUE the support for OCTOSPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_WSPI_USE_OCTOSPI1) || defined(__DOXYGEN__) +#define STM32_WSPI_USE_OCTOSPI1 FALSE +#endif + +/** + * @brief WSPID2 driver enable switch. + * @details If set to @p TRUE the support for OCTOSPI2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_WSPI_USE_OCTOSPI2) || defined(__DOXYGEN__) +#define STM32_WSPI_USE_OCTOSPI2 FALSE +#endif + +/** + * @brief OCTOSPI1 prescaler setting. + * @note This is the prescaler divider value 1..256. The maximum frequency + * varies depending on the STM32 model and operating conditions, + * find the details in the data sheet. + */ +#if !defined(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI1_PRESCALER_VALUE 1 +#endif + +/** + * @brief OCTOSPI2 prescaler setting. + * @note This is the prescaler divider value 1..256. The maximum frequency + * varies depending on the STM32 model and operating conditions, + * find the details in the data sheet. + */ +#if !defined(STM32_WSPI_OCTOSPI2_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_PRESCALER_VALUE 1 +#endif + +/** + * @brief OCTOSPI1 interrupt priority level setting. + */ +#if !defined(STM32_WSPI_OCTOSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief OCTOSPI2 interrupt priority level setting. + */ +#if !defined(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief OCTOSPI1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief OCTOSPI2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief OCTOSPI1 DMA interrupt priority level setting. + */ +#if !defined(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY 10 +#endif + +/** + * @brief OCTOSPI2 DMA interrupt priority level setting. + */ +#if !defined(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY 10 +#endif + +/** + * @brief OCTOSPI DMA error hook. + */ +#if !defined(STM32_WSPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_WSPI_DMA_ERROR_HOOK(wspip) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_OCTOSPI1) +#define STM32_HAS_OCTOSPI1 FALSE +#endif + +#if !defined(STM32_HAS_OCTOSPI2) +#define STM32_HAS_OCTOSPI2 FALSE +#endif + +#if STM32_WSPI_USE_OCTOSPI1 && !STM32_HAS_OCTOSPI1 +#error "OCTOSPI1 not present in the selected device" +#endif + +#if STM32_WSPI_USE_OCTOSPI2 && !STM32_HAS_OCTOSPI2 +#error "OCTOSPI2 not present in the selected device" +#endif + +#if !STM32_WSPI_USE_OCTOSPI1 && !STM32_WSPI_USE_OCTOSPI2 +#error "WSPI driver activated but no OCTOSPI peripheral assigned" +#endif + +/* Check on OCTOSPI prescaler setting.*/ +#if (STM32_WSPI_OCTOSPI1_PRESCALER_VALUE < 1) || \ + (STM32_WSPI_OCTOSPI1_PRESCALER_VALUE > 256) +#error "STM32_WSPI_OCTOSPI1_PRESCALER_VALUE not within 1..256" +#endif + +#if (STM32_WSPI_OCTOSPI2_PRESCALER_VALUE < 1) || \ + (STM32_WSPI_OCTOSPI2_PRESCALER_VALUE > 256) +#error "STM32_WSPI_OCTOSPI2_PRESCALER_VALUE not within 1..256" +#endif + +/* Check on IRQ priorities.*/ +#if STM32_WSPI_USE_OCTOSPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OCTOSPI1" +#endif + +#if STM32_WSPI_USE_OCTOSPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OCTOSPI2" +#endif + +#if STM32_WSPI_USE_OCTOSPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OCTOSPI1 DMA" +#endif + +#if STM32_WSPI_USE_OCTOSPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OCTOSPI2 DMA" +#endif + +/* Check on the presence of the DMA channels settings in mcuconf.h.*/ +#if STM32_WSPI_USE_OCTOSPI1 && !defined(STM32_WSPI_OCTOSPI1_DMA_STREAM) +#error "OCTOSPI1 DMA stream not defined" +#endif + +#if STM32_WSPI_USE_OCTOSPI2 && !defined(STM32_WSPI_OCTOSPI2_DMA_STREAM) +#error "OCTOSPI2 DMA stream not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_WSPI_USE_OCTOSPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_OCTOSPI1_DMA_STREAM) +#error "invalid DMA stream associated to OCTOSPI1" +#endif + +#if STM32_WSPI_USE_OCTOSPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_OCTOSPI2_DMA_STREAM) +#error "invalid DMA stream associated to OCTOSPI2" +#endif + +/* Check on DMA channels priority.*/ +#if STM32_WSPI_USE_OCTOSPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to OCTOSPI1" +#endif + +#if STM32_WSPI_USE_OCTOSPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to OCTOSPI2" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the WSPI configuration structure. + */ +#define wspi_lld_config_fields \ + /* DCR1 register initialization data.*/ \ + uint32_t dcr1; \ + /* DCR2 register initialization data. The prescaler field is internally \ + ORed to this field, leave it to zero.*/ \ + uint32_t dcr2; \ + /* DCR3 register initialization data.*/ \ + uint32_t dcr3; \ + /* DCR4 register initialization data.*/ \ + uint32_t dcr4 + +/** + * @brief Low level fields of the WSPI driver structure. + */ +#define wspi_lld_driver_fields \ + /* Pointer to the OCTOSPIx registers block.*/ \ + OCTOSPI_TypeDef *ospi; \ + /* OCTOSPI DMA stream.*/ \ + const stm32_dma_stream_t *dma; \ + /* OCTOSPI DMA mode bit mask.*/ \ + uint32_t dmamode + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (STM32_WSPI_USE_OCTOSPI1 == TRUE) && !defined(__DOXYGEN__) +extern WSPIDriver WSPID1; +#endif + +#if (STM32_WSPI_USE_OCTOSPI2 == TRUE) && !defined(__DOXYGEN__) +extern WSPIDriver WSPID2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void wspi_lld_init(void); + void wspi_lld_start(WSPIDriver *wspip); + void wspi_lld_stop(WSPIDriver *wspip); + void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp); + void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf); + void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf); +#if WSPI_SUPPORTS_MEMMAP == TRUE + void wspi_lld_map_flash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp); + void wspi_lld_unmap_flash(WSPIDriver *wspip); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_WSPI */ + +#endif /* HAL_WSPI_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/OTGv1/driver.mk b/os/hal/ports/STM32/LLD/OTGv1/driver.mk index 197c1d281d..16250123ba 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/driver.mk +++ b/os/hal/ports/STM32/LLD/OTGv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1 diff --git a/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c index 76f7c320b8..75d23c569a 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c +++ b/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c @@ -1,1264 +1,1264 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file OTGv1/hal_usb_lld.c - * @brief STM32 USB subsystem low level driver source. - * - * @addtogroup USB - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_USB || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define TRDT_VALUE_FS 5 -#define TRDT_VALUE_HS 9 - -#define EP0_MAX_INSIZE 64 -#define EP0_MAX_OUTSIZE 64 - -#if STM32_OTG_STEPPING == 1 -#if defined(BOARD_OTG_NOVBUSSENS) -#define GCCFG_INIT_VALUE (GCCFG_NOVBUSSENS | GCCFG_VBUSASEN | \ - GCCFG_VBUSBSEN | GCCFG_PWRDWN) -#else -#define GCCFG_INIT_VALUE (GCCFG_VBUSASEN | GCCFG_VBUSBSEN | \ - GCCFG_PWRDWN) -#endif - -#elif STM32_OTG_STEPPING == 2 -#if defined(BOARD_OTG_NOVBUSSENS) -#define GCCFG_INIT_VALUE GCCFG_PWRDWN -#else -#define GCCFG_INIT_VALUE (GCCFG_VBDEN | GCCFG_PWRDWN) -#endif - -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief OTG_FS driver identifier.*/ -#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) -USBDriver USBD1; -#endif - -/** @brief OTG_HS driver identifier.*/ -#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) -USBDriver USBD2; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief EP0 state. - * @note It is an union because IN and OUT endpoints are never used at the - * same time for EP0. - */ -static union { - /** - * @brief IN EP0 state. - */ - USBInEndpointState in; - /** - * @brief OUT EP0 state. - */ - USBOutEndpointState out; -} ep0_state; - -/** - * @brief Buffer for the EP0 setup packets. - */ -static uint8_t ep0setup_buffer[8]; - -/** - * @brief EP0 initialization structure. - */ -static const USBEndpointConfig ep0config = { - USB_EP_MODE_TYPE_CTRL, - _usb_ep0setup, - _usb_ep0in, - _usb_ep0out, - 0x40, - 0x40, - &ep0_state.in, - &ep0_state.out, - 1, - ep0setup_buffer -}; - -#if STM32_USB_USE_OTG1 -static const stm32_otg_params_t fsparams = { - STM32_USB_OTG1_RX_FIFO_SIZE / 4, - STM32_OTG1_FIFO_MEM_SIZE, - STM32_OTG1_ENDPOINTS -}; -#endif - -#if STM32_USB_USE_OTG2 -static const stm32_otg_params_t hsparams = { - STM32_USB_OTG2_RX_FIFO_SIZE / 4, - STM32_OTG2_FIFO_MEM_SIZE, - STM32_OTG2_ENDPOINTS -}; -#endif - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static void otg_core_reset(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - /* Wait AHB idle condition.*/ - while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0) - ; - - /* Core reset and delay of at least 3 PHY cycles.*/ - otgp->GRSTCTL = GRSTCTL_CSRST; - osalSysPolledDelayX(12); - while ((otgp->GRSTCTL & GRSTCTL_CSRST) != 0) - ; - - osalSysPolledDelayX(18); - - /* Wait AHB idle condition again.*/ - while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0) - ; -} - -static void otg_disable_ep(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - unsigned i; - - for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { - - if ((otgp->ie[i].DIEPCTL & DIEPCTL_EPENA) != 0U) { - otgp->ie[i].DIEPCTL |= DIEPCTL_EPDIS; - } - - if ((otgp->oe[i].DOEPCTL & DIEPCTL_EPENA) != 0U) { - otgp->oe[i].DOEPCTL |= DIEPCTL_EPDIS; - } - - otgp->ie[i].DIEPINT = 0xFFFFFFFF; - otgp->oe[i].DOEPINT = 0xFFFFFFFF; - } - otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); -} - -static void otg_rxfifo_flush(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - otgp->GRSTCTL = GRSTCTL_RXFFLSH; - while ((otgp->GRSTCTL & GRSTCTL_RXFFLSH) != 0) - ; - /* Wait for 3 PHY Clocks.*/ - osalSysPolledDelayX(18); -} - -static void otg_txfifo_flush(USBDriver *usbp, uint32_t fifo) { - stm32_otg_t *otgp = usbp->otg; - - otgp->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH; - while ((otgp->GRSTCTL & GRSTCTL_TXFFLSH) != 0) - ; - /* Wait for 3 PHY Clocks.*/ - osalSysPolledDelayX(18); -} - -/** - * @brief Resets the FIFO RAM memory allocator. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void otg_ram_reset(USBDriver *usbp) { - - usbp->pmnext = usbp->otgparams->rx_fifo_size; -} - -/** - * @brief Allocates a block from the FIFO RAM memory. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] size size of the packet buffer to allocate in words - * - * @notapi - */ -static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) { - uint32_t next; - - next = usbp->pmnext; - usbp->pmnext += size; - osalDbgAssert(usbp->pmnext <= usbp->otgparams->otg_ram_size, - "OTG FIFO memory overflow"); - return next; -} - -/** - * @brief Writes to a TX FIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[in] buf buffer where to copy the endpoint data - * @param[in] n maximum number of bytes to copy - * - * @notapi - */ -static void otg_fifo_write_from_buffer(volatile uint32_t *fifop, - const uint8_t *buf, - size_t n) { - - osalDbgAssert(n > 0, "is zero"); - - while (true) { - *fifop = *((uint32_t *)buf); - if (n <= 4) { - break; - } - n -= 4; - buf += 4; - } -} - -/** - * @brief Reads a packet from the RXFIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[out] buf buffer where to copy the endpoint data - * @param[in] n number of bytes to pull from the FIFO - * @param[in] max number of bytes to copy into the buffer - * - * @notapi - */ -static void otg_fifo_read_to_buffer(volatile uint32_t *fifop, - uint8_t *buf, - size_t n, - size_t max) { - uint32_t w = 0; - size_t i = 0; - - while (i < n) { - if ((i & 3) == 0) { - w = *fifop; - } - if (i < max) { - *buf++ = (uint8_t)w; - w >>= 8; - } - i++; - } -} - -/** - * @brief Incoming packets handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void otg_rxfifo_handler(USBDriver *usbp) { - uint32_t sts, cnt, ep; - - /* Popping the event word out of the RX FIFO.*/ - sts = usbp->otg->GRXSTSP; - - /* Event details.*/ - cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; - ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; - - switch (sts & GRXSTSP_PKTSTS_MASK) { - case GRXSTSP_SETUP_DATA: - otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf, - cnt, 8); - break; - case GRXSTSP_SETUP_COMP: - break; - case GRXSTSP_OUT_DATA: - otg_fifo_read_to_buffer(usbp->otg->FIFO[0], - usbp->epc[ep]->out_state->rxbuf, - cnt, - usbp->epc[ep]->out_state->rxsize - - usbp->epc[ep]->out_state->rxcnt); - usbp->epc[ep]->out_state->rxbuf += cnt; - usbp->epc[ep]->out_state->rxcnt += cnt; - break; - case GRXSTSP_OUT_COMP: - break; - case GRXSTSP_OUT_GLOBAL_NAK: - break; - default: - break; - } -} - -/** - * @brief Outgoing packets handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static bool otg_txfifo_handler(USBDriver *usbp, usbep_t ep) { - - /* The TXFIFO is filled until there is space and data to be transmitted.*/ - while (true) { - uint32_t n; - - /* Transaction end condition.*/ - if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) { -#if 1 - usbp->otg->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep); -#endif - return true; - } - - /* Number of bytes remaining in current transaction.*/ - n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt; - if (n > usbp->epc[ep]->in_maxsize) - n = usbp->epc[ep]->in_maxsize; - - /* Checks if in the TXFIFO there is enough space to accommodate the - next packet.*/ - if (((usbp->otg->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n) - return false; - -#if STM32_USB_OTGFIFO_FILL_BASEPRI - __set_BASEPRI(CORTEX_PRIO_MASK(STM32_USB_OTGFIFO_FILL_BASEPRI)); -#endif - otg_fifo_write_from_buffer(usbp->otg->FIFO[ep], - usbp->epc[ep]->in_state->txbuf, - n); - usbp->epc[ep]->in_state->txbuf += n; - usbp->epc[ep]->in_state->txcnt += n; -#if STM32_USB_OTGFIFO_FILL_BASEPRI - __set_BASEPRI(0); -#endif - } -} - -/** - * @brief Generic endpoint IN handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { - stm32_otg_t *otgp = usbp->otg; - uint32_t epint = otgp->ie[ep].DIEPINT; - - otgp->ie[ep].DIEPINT = epint; - - if (epint & DIEPINT_TOC) { - /* Timeouts not handled yet, not sure how to handle.*/ - } - if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) { - /* Transmit transfer complete.*/ - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - if (isp->txsize < isp->totsize) { - /* In case the transaction covered only part of the total transfer - then another transaction is immediately started in order to - cover the remaining.*/ - isp->txsize = isp->totsize - isp->txsize; - isp->txcnt = 0; - osalSysLockFromISR(); - usb_lld_start_in(usbp, ep); - osalSysUnlockFromISR(); - } - else { - /* End on IN transfer.*/ - _usb_isr_invoke_in_cb(usbp, ep); - } - } - if ((epint & DIEPINT_TXFE) && - (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) { - /* TX FIFO empty or emptying.*/ - otg_txfifo_handler(usbp, ep); - } -} - -/** - * @brief Generic endpoint OUT handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { - stm32_otg_t *otgp = usbp->otg; - uint32_t epint = otgp->oe[ep].DOEPINT; - - /* Resets all EP IRQ sources.*/ - otgp->oe[ep].DOEPINT = epint; - - if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) { - /* Setup packets handling, setup packets are handled using a - specific callback.*/ - _usb_isr_invoke_setup_cb(usbp, ep); - } - - if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) { - USBOutEndpointState *osp; - - /* OUT state structure pointer for this endpoint.*/ - osp = usbp->epc[ep]->out_state; - - /* EP0 requires special handling.*/ - if (ep == 0) { - -#if defined(STM32_OTG_SEQUENCE_WORKAROUND) - /* If an OUT transaction end interrupt is processed while the state - machine is not in an OUT state then it is ignored, this is caused - on some devices (L4) apparently injecting spurious data complete - words in the RX FIFO.*/ - if ((usbp->ep0state & USB_OUT_STATE) == 0) - return; -#endif - - /* In case the transaction covered only part of the total transfer - then another transaction is immediately started in order to - cover the remaining.*/ - if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) && - (osp->rxsize < osp->totsize)) { - osp->rxsize = osp->totsize - osp->rxsize; - osp->rxcnt = 0; - osalSysLockFromISR(); - usb_lld_start_out(usbp, ep); - osalSysUnlockFromISR(); - return; - } - } - - /* End on OUT transfer.*/ - _usb_isr_invoke_out_cb(usbp, ep); - } -} - -/** - * @brief Isochronous IN transfer failed handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void otg_isoc_in_failed_handler(USBDriver *usbp) { - usbep_t ep; - stm32_otg_t *otgp = usbp->otg; - - for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { - if (((otgp->ie[ep].DIEPCTL & DIEPCTL_EPTYP_MASK) == DIEPCTL_EPTYP_ISO) && - ((otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) != 0)) { - /* Endpoint enabled -> ISOC IN transfer failed.*/ - /* Disable endpoint.*/ - otgp->ie[ep].DIEPCTL |= (DIEPCTL_EPDIS | DIEPCTL_SNAK); - while (otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) - ; - - /* Flush FIFO.*/ - otg_txfifo_flush(usbp, ep); - - /* Prepare data for next frame.*/ - _usb_isr_invoke_in_cb(usbp, ep); - } - } -} - -/** - * @brief Isochronous OUT transfer failed handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void otg_isoc_out_failed_handler(USBDriver *usbp) { - usbep_t ep; - stm32_otg_t *otgp = usbp->otg; - - for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { - if (((otgp->oe[ep].DOEPCTL & DOEPCTL_EPTYP_MASK) == DOEPCTL_EPTYP_ISO) && - ((otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) != 0)) { -#if 0 - /* Endpoint enabled -> ISOC OUT transfer failed.*/ - /* Disable endpoint.*/ - /* CHTODO:: Core stucks here */ - otgp->oe[ep].DOEPCTL |= (DOEPCTL_EPDIS | DOEPCTL_SNAK); - while (otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) - ; -#endif - /* Prepare transfer for next frame.*/ - _usb_isr_invoke_out_cb(usbp, ep); - } - } -} - -/** - * @brief OTG shared ISR. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void usb_lld_serve_interrupt(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - uint32_t sts, src; - - sts = otgp->GINTSTS; - sts &= otgp->GINTMSK; - otgp->GINTSTS = sts; - - /* Reset interrupt handling.*/ - if (sts & GINTSTS_USBRST) { - /* Default reset action.*/ - _usb_reset(usbp); - - /* Preventing execution of more handlers, the core has been reset.*/ - return; - } - - /* Wake-up handling.*/ - if (sts & GINTSTS_WKUPINT) { - /* If clocks are gated off, turn them back on (may be the case if - coming out of suspend mode).*/ - if (otgp->PCGCCTL & (PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK)) { - /* Set to zero to un-gate the USB core clocks.*/ - otgp->PCGCCTL &= ~(PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK); - } - - /* Clear the Remote Wake-up Signaling.*/ - otgp->DCTL &= ~DCTL_RWUSIG; - - _usb_wakeup(usbp); - } - - /* Suspend handling.*/ - if (sts & GINTSTS_USBSUSP) { - /* Stopping all ongoing transfers.*/ - otg_disable_ep(usbp); - - /* Default suspend action.*/ - _usb_suspend(usbp); - } - - /* Enumeration done.*/ - if (sts & GINTSTS_ENUMDNE) { - /* Full or High speed timing selection.*/ - if ((otgp->DSTS & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HS_480) { - otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) | - GUSBCFG_TRDT(TRDT_VALUE_HS); - } - else { - otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) | - GUSBCFG_TRDT(TRDT_VALUE_FS); - } - } - - /* SOF interrupt handling.*/ - if (sts & GINTSTS_SOF) { - _usb_isr_invoke_sof_cb(usbp); - } - - /* Isochronous IN failed handling */ - if (sts & GINTSTS_IISOIXFR) { - otg_isoc_in_failed_handler(usbp); - } - - /* Isochronous OUT failed handling */ - if (sts & GINTSTS_IISOOXFR) { - otg_isoc_out_failed_handler(usbp); - } - - /* Performing the whole FIFO emptying in the ISR, it is advised to keep - this IRQ at a very low priority level.*/ - if ((sts & GINTSTS_RXFLVL) != 0U) { - otg_rxfifo_handler(usbp); - } - - /* IN/OUT endpoints event handling.*/ - src = otgp->DAINT; - if (sts & GINTSTS_OEPINT) { - if (src & (1 << 16)) - otg_epout_handler(usbp, 0); - if (src & (1 << 17)) - otg_epout_handler(usbp, 1); - if (src & (1 << 18)) - otg_epout_handler(usbp, 2); - if (src & (1 << 19)) - otg_epout_handler(usbp, 3); -#if USB_MAX_ENDPOINTS >= 4 - if (src & (1 << 20)) - otg_epout_handler(usbp, 4); -#endif -#if USB_MAX_ENDPOINTS >= 5 - if (src & (1 << 21)) - otg_epout_handler(usbp, 5); -#endif -#if USB_MAX_ENDPOINTS >= 6 - if (src & (1 << 22)) - otg_epout_handler(usbp, 6); -#endif -#if USB_MAX_ENDPOINTS >= 7 - if (src & (1 << 23)) - otg_epout_handler(usbp, 7); -#endif -#if USB_MAX_ENDPOINTS >= 8 - if (src & (1 << 24)) - otg_epout_handler(usbp, 8); -#endif - } - if (sts & GINTSTS_IEPINT) { - if (src & (1 << 0)) - otg_epin_handler(usbp, 0); - if (src & (1 << 1)) - otg_epin_handler(usbp, 1); - if (src & (1 << 2)) - otg_epin_handler(usbp, 2); - if (src & (1 << 3)) - otg_epin_handler(usbp, 3); -#if USB_MAX_ENDPOINTS >= 4 - if (src & (1 << 4)) - otg_epin_handler(usbp, 4); -#endif -#if USB_MAX_ENDPOINTS >= 5 - if (src & (1 << 5)) - otg_epin_handler(usbp, 5); -#endif -#if USB_MAX_ENDPOINTS >= 6 - if (src & (1 << 6)) - otg_epin_handler(usbp, 6); -#endif -#if USB_MAX_ENDPOINTS >= 7 - if (src & (1 << 7)) - otg_epin_handler(usbp, 7); -#endif -#if USB_MAX_ENDPOINTS >= 8 - if (src & (1 << 8)) - otg_epin_handler(usbp, 8); -#endif - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) -/** - * @brief OTG1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_OTG1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - usb_lld_serve_interrupt(&USBD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) -/** - * @brief OTG2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_OTG2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - usb_lld_serve_interrupt(&USBD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level USB driver initialization. - * - * @notapi - */ -void usb_lld_init(void) { - - /* Driver initialization.*/ -#if STM32_USB_USE_OTG1 - usbObjectInit(&USBD1); - USBD1.otg = OTG_FS; - USBD1.otgparams = &fsparams; - -#endif - -#if STM32_USB_USE_OTG2 - usbObjectInit(&USBD2); - USBD2.otg = OTG_HS; - USBD2.otgparams = &hsparams; -#endif -} - -/** - * @brief Configures and activates the USB peripheral. - * @note Starting the OTG cell can be a slow operation carried out with - * interrupts disabled, perform it before starting time-critical - * operations. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_start(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - if (usbp->state == USB_STOP) { - /* Clock activation.*/ - -#if STM32_USB_USE_OTG1 - if (&USBD1 == usbp) { - /* OTG FS clock enable and reset.*/ - rccEnableOTG_FS(true); - rccResetOTG_FS(); - - /* Enables IRQ vector.*/ - nvicEnableVector(STM32_OTG1_NUMBER, STM32_USB_OTG1_IRQ_PRIORITY); - - /* - Forced device mode. - - USB turn-around time = TRDT_VALUE_FS. - - Full Speed 1.1 PHY.*/ - otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) | - GUSBCFG_PHYSEL; - - /* 48MHz 1.1 PHY.*/ - otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; - } -#endif - -#if STM32_USB_USE_OTG2 - if (&USBD2 == usbp) { - /* OTG HS clock enable and reset.*/ - rccEnableOTG_HS(true); - rccResetOTG_HS(); - - /* ULPI clock is managed depending on the presence of an external - PHY.*/ -#if defined(BOARD_OTG2_USES_ULPI) - rccEnableOTG_HSULPI(true); -#else - /* Workaround for the problem described here: - http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1798.*/ - rccDisableOTG_HSULPI(); -#endif - - /* Enables IRQ vector.*/ - nvicEnableVector(STM32_OTG2_NUMBER, STM32_USB_OTG2_IRQ_PRIORITY); - - /* - Forced device mode. - - USB turn-around time = TRDT_VALUE_HS or TRDT_VALUE_FS.*/ -#if defined(BOARD_OTG2_USES_ULPI) - /* High speed ULPI PHY.*/ - otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) | - GUSBCFG_SRPCAP | GUSBCFG_HNPCAP; -#else - otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) | - GUSBCFG_PHYSEL; -#endif - -#if defined(BOARD_OTG2_USES_ULPI) -#if STM32_USE_USB_OTG2_HS - /* USB 2.0 High Speed PHY in HS mode.*/ - otgp->DCFG = 0x02200000 | DCFG_DSPD_HS; -#else - /* USB 2.0 High Speed PHY in FS mode.*/ - otgp->DCFG = 0x02200000 | DCFG_DSPD_HS_FS; -#endif -#else - /* 48MHz 1.1 PHY.*/ - otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; -#endif - } -#endif - - /* PHY enabled.*/ - otgp->PCGCCTL = 0; - - /* VBUS sensing and transceiver enabled.*/ - otgp->GOTGCTL = GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; - -#if defined(BOARD_OTG2_USES_ULPI) -#if STM32_USB_USE_OTG1 - if (&USBD1 == usbp) { - otgp->GCCFG = GCCFG_INIT_VALUE; - } -#endif - -#if STM32_USB_USE_OTG2 - if (&USBD2 == usbp) { - otgp->GCCFG = 0; - } -#endif -#else - otgp->GCCFG = GCCFG_INIT_VALUE; -#endif - - /* Soft core reset.*/ - otg_core_reset(usbp); - - /* Interrupts on TXFIFOs half empty.*/ - otgp->GAHBCFG = 0; - - /* Endpoints re-initialization.*/ - otg_disable_ep(usbp); - - /* Clear all pending Device Interrupts, only the USB Reset interrupt - is required initially.*/ - otgp->DIEPMSK = 0; - otgp->DOEPMSK = 0; - otgp->DAINTMSK = 0; - if (usbp->config->sof_cb == NULL) - otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | - GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | - GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM; - else - otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | - GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | - GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM | - GINTMSK_SOFM; - - /* Clears all pending IRQs, if any. */ - otgp->GINTSTS = 0xFFFFFFFF; - - /* Global interrupts enable.*/ - otgp->GAHBCFG |= GAHBCFG_GINTMSK; - } -} - -/** - * @brief Deactivates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_stop(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - /* If in ready state then disables the USB clock.*/ - if (usbp->state != USB_STOP) { - - /* Disabling all endpoints in case the driver has been stopped while - active.*/ - otg_disable_ep(usbp); - - otgp->DAINTMSK = 0; - otgp->GAHBCFG = 0; - otgp->GCCFG = 0; - -#if STM32_USB_USE_OTG1 - if (&USBD1 == usbp) { - nvicDisableVector(STM32_OTG1_NUMBER); - rccDisableOTG_FS(); - } -#endif - -#if STM32_USB_USE_OTG2 - if (&USBD2 == usbp) { - nvicDisableVector(STM32_OTG2_NUMBER); - rccDisableOTG_HS(); -#if defined(BOARD_OTG2_USES_ULPI) - rccDisableOTG_HSULPI() -#endif - } -#endif - } -} - -/** - * @brief USB low level reset routine. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_reset(USBDriver *usbp) { - unsigned i; - stm32_otg_t *otgp = usbp->otg; - - /* Flush the Tx FIFO.*/ - otg_txfifo_flush(usbp, 0); - - /* Endpoint interrupts all disabled and cleared.*/ - otgp->DIEPEMPMSK = 0; - otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); - - /* All endpoints in NAK mode, interrupts cleared.*/ - for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { - otgp->ie[i].DIEPCTL = DIEPCTL_SNAK; - otgp->oe[i].DOEPCTL = DOEPCTL_SNAK; - otgp->ie[i].DIEPINT = 0xFFFFFFFF; - otgp->oe[i].DOEPINT = 0xFFFFFFFF; - } - - /* Resets the FIFO memory allocator.*/ - otg_ram_reset(usbp); - - /* Receive FIFO size initialization, the address is always zero.*/ - otgp->GRXFSIZ = usbp->otgparams->rx_fifo_size; - otg_rxfifo_flush(usbp); - - /* Resets the device address to zero.*/ - otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0); - - /* Enables also EP-related interrupt sources.*/ - otgp->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; - otgp->DIEPMSK = DIEPMSK_TOCM | DIEPMSK_XFRCM; - otgp->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM; - - /* EP0 initialization, it is a special case.*/ - usbp->epc[0] = &ep0config; - otgp->oe[0].DOEPTSIZ = DOEPTSIZ_STUPCNT(3); - otgp->oe[0].DOEPCTL = DOEPCTL_SD0PID | DOEPCTL_USBAEP | DOEPCTL_EPTYP_CTRL | - DOEPCTL_MPSIZ(ep0config.out_maxsize); - otgp->ie[0].DIEPTSIZ = 0; - otgp->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | - DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize); - otgp->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) | - DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, - ep0config.in_maxsize / 4)); -} - -/** - * @brief Sets the USB address. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_set_address(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(usbp->address); -} - -/** - * @brief Enables an endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { - uint32_t ctl, fsize; - stm32_otg_t *otgp = usbp->otg; - - /* IN and OUT common parameters.*/ - switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) { - case USB_EP_MODE_TYPE_CTRL: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL; - break; - case USB_EP_MODE_TYPE_ISOC: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO; - break; - case USB_EP_MODE_TYPE_BULK: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK; - break; - case USB_EP_MODE_TYPE_INTR: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR; - break; - default: - return; - } - - /* OUT endpoint activation or deactivation.*/ - otgp->oe[ep].DOEPTSIZ = 0; - if (usbp->epc[ep]->out_state != NULL) { - otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize); - otgp->DAINTMSK |= DAINTMSK_OEPM(ep); - } - else { - otgp->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP; - otgp->DAINTMSK &= ~DAINTMSK_OEPM(ep); - } - - /* IN endpoint activation or deactivation.*/ - otgp->ie[ep].DIEPTSIZ = 0; - if (usbp->epc[ep]->in_state != NULL) { - /* FIFO allocation for the IN endpoint.*/ - fsize = usbp->epc[ep]->in_maxsize / 4; - if (usbp->epc[ep]->in_multiplier > 1) - fsize *= usbp->epc[ep]->in_multiplier; - otgp->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | - DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); - otg_txfifo_flush(usbp, ep); - - otgp->ie[ep].DIEPCTL = ctl | - DIEPCTL_TXFNUM(ep) | - DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize); - otgp->DAINTMSK |= DAINTMSK_IEPM(ep); - } - else { - otgp->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/ - otg_txfifo_flush(usbp, ep); - otgp->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP; - otgp->DAINTMSK &= ~DAINTMSK_IEPM(ep); - } -} - -/** - * @brief Disables all the active endpoints except the endpoint zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_disable_endpoints(USBDriver *usbp) { - - /* Resets the FIFO memory allocator.*/ - otg_ram_reset(usbp); - - /* Disabling all endpoints.*/ - otg_disable_ep(usbp); -} - -/** - * @brief Returns the status of an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { - uint32_t ctl; - - (void)usbp; - - ctl = usbp->otg->oe[ep].DOEPCTL; - if (!(ctl & DOEPCTL_USBAEP)) - return EP_STATUS_DISABLED; - if (ctl & DOEPCTL_STALL) - return EP_STATUS_STALLED; - return EP_STATUS_ACTIVE; -} - -/** - * @brief Returns the status of an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { - uint32_t ctl; - - (void)usbp; - - ctl = usbp->otg->ie[ep].DIEPCTL; - if (!(ctl & DIEPCTL_USBAEP)) - return EP_STATUS_DISABLED; - if (ctl & DIEPCTL_STALL) - return EP_STATUS_STALLED; - return EP_STATUS_ACTIVE; -} - -/** - * @brief Reads a setup packet from the dedicated packet buffer. - * @details This function must be invoked in the context of the @p setup_cb - * callback in order to read the received setup packet. - * @pre In order to use this function the endpoint must have been - * initialized as a control endpoint. - * @post The endpoint is ready to accept another packet. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * - * @notapi - */ -void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { - - memcpy(buf, usbp->epc[ep]->setup_buf, 8); -} - -/** - * @brief Starts a receive operation on an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { - uint32_t pcnt, rxsize; - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - /* Transfer initialization.*/ - osp->totsize = osp->rxsize; - if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE)) - osp->rxsize = EP0_MAX_OUTSIZE; - - /* Transaction size is rounded to a multiple of packet size because the - following requirement in the RM: - "For OUT transfers, the transfer size field in the endpoint's transfer - size register must be a multiple of the maximum packet size of the - endpoint, adjusted to the Word boundary".*/ - pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) / - usbp->epc[ep]->out_maxsize; - rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU; - - /*Setting up transaction parameters in DOEPTSIZ.*/ - usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) | - DOEPTSIZ_XFRSIZ(rxsize); - - /* Special case of isochronous endpoint.*/ - if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { - /* Odd/even bit toggling for isochronous endpoint.*/ - if (usbp->otg->DSTS & DSTS_FNSOF_ODD) - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM; - else - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM; - } - - /* Starting operation.*/ - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK; -} - -/** - * @brief Starts a transmit operation on an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - /* Transfer initialization.*/ - isp->totsize = isp->txsize; - if (isp->txsize == 0) { - /* Special case, sending zero size packet.*/ - usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0); - } - else { - if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE)) - isp->txsize = EP0_MAX_INSIZE; - - /* Normal case.*/ - uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / - usbp->epc[ep]->in_maxsize; - /* CHTODO: Support more than one packet per frame for isochronous transfers.*/ - usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) | - DIEPTSIZ_XFRSIZ(isp->txsize); - } - - /* Special case of isochronous endpoint.*/ - if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { - /* Odd/even bit toggling.*/ - if (usbp->otg->DSTS & DSTS_FNSOF_ODD) - usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SEVNFRM; - else - usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM; - } - - /* Starting operation.*/ - usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; - usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); -} - -/** - * @brief Brings an OUT endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { - - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_STALL; -} - -/** - * @brief Brings an IN endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { - - usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_STALL; -} - -/** - * @brief Brings an OUT endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { - - usbp->otg->oe[ep].DOEPCTL &= ~DOEPCTL_STALL; -} - -/** - * @brief Brings an IN endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { - - usbp->otg->ie[ep].DIEPCTL &= ~DIEPCTL_STALL; -} - -#endif /* HAL_USE_USB */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file OTGv1/hal_usb_lld.c + * @brief STM32 USB subsystem low level driver source. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define TRDT_VALUE_FS 5 +#define TRDT_VALUE_HS 9 + +#define EP0_MAX_INSIZE 64 +#define EP0_MAX_OUTSIZE 64 + +#if STM32_OTG_STEPPING == 1 +#if defined(BOARD_OTG_NOVBUSSENS) +#define GCCFG_INIT_VALUE (GCCFG_NOVBUSSENS | GCCFG_VBUSASEN | \ + GCCFG_VBUSBSEN | GCCFG_PWRDWN) +#else +#define GCCFG_INIT_VALUE (GCCFG_VBUSASEN | GCCFG_VBUSBSEN | \ + GCCFG_PWRDWN) +#endif + +#elif STM32_OTG_STEPPING == 2 +#if defined(BOARD_OTG_NOVBUSSENS) +#define GCCFG_INIT_VALUE GCCFG_PWRDWN +#else +#define GCCFG_INIT_VALUE (GCCFG_VBDEN | GCCFG_PWRDWN) +#endif + +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief OTG_FS driver identifier.*/ +#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/** @brief OTG_HS driver identifier.*/ +#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) +USBDriver USBD2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + * @note It is an union because IN and OUT endpoints are never used at the + * same time for EP0. + */ +static union { + /** + * @brief IN EP0 state. + */ + USBInEndpointState in; + /** + * @brief OUT EP0 state. + */ + USBOutEndpointState out; +} ep0_state; + +/** + * @brief Buffer for the EP0 setup packets. + */ +static uint8_t ep0setup_buffer[8]; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + USB_EP_MODE_TYPE_CTRL, + _usb_ep0setup, + _usb_ep0in, + _usb_ep0out, + 0x40, + 0x40, + &ep0_state.in, + &ep0_state.out, + 1, + ep0setup_buffer +}; + +#if STM32_USB_USE_OTG1 +static const stm32_otg_params_t fsparams = { + STM32_USB_OTG1_RX_FIFO_SIZE / 4, + STM32_OTG1_FIFO_MEM_SIZE, + STM32_OTG1_ENDPOINTS +}; +#endif + +#if STM32_USB_USE_OTG2 +static const stm32_otg_params_t hsparams = { + STM32_USB_OTG2_RX_FIFO_SIZE / 4, + STM32_OTG2_FIFO_MEM_SIZE, + STM32_OTG2_ENDPOINTS +}; +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void otg_core_reset(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + /* Wait AHB idle condition.*/ + while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0) + ; + + /* Core reset and delay of at least 3 PHY cycles.*/ + otgp->GRSTCTL = GRSTCTL_CSRST; + osalSysPolledDelayX(12); + while ((otgp->GRSTCTL & GRSTCTL_CSRST) != 0) + ; + + osalSysPolledDelayX(18); + + /* Wait AHB idle condition again.*/ + while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0) + ; +} + +static void otg_disable_ep(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + unsigned i; + + for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { + + if ((otgp->ie[i].DIEPCTL & DIEPCTL_EPENA) != 0U) { + otgp->ie[i].DIEPCTL |= DIEPCTL_EPDIS; + } + + if ((otgp->oe[i].DOEPCTL & DIEPCTL_EPENA) != 0U) { + otgp->oe[i].DOEPCTL |= DIEPCTL_EPDIS; + } + + otgp->ie[i].DIEPINT = 0xFFFFFFFF; + otgp->oe[i].DOEPINT = 0xFFFFFFFF; + } + otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); +} + +static void otg_rxfifo_flush(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + otgp->GRSTCTL = GRSTCTL_RXFFLSH; + while ((otgp->GRSTCTL & GRSTCTL_RXFFLSH) != 0) + ; + /* Wait for 3 PHY Clocks.*/ + osalSysPolledDelayX(18); +} + +static void otg_txfifo_flush(USBDriver *usbp, uint32_t fifo) { + stm32_otg_t *otgp = usbp->otg; + + otgp->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH; + while ((otgp->GRSTCTL & GRSTCTL_TXFFLSH) != 0) + ; + /* Wait for 3 PHY Clocks.*/ + osalSysPolledDelayX(18); +} + +/** + * @brief Resets the FIFO RAM memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_ram_reset(USBDriver *usbp) { + + usbp->pmnext = usbp->otgparams->rx_fifo_size; +} + +/** + * @brief Allocates a block from the FIFO RAM memory. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] size size of the packet buffer to allocate in words + * + * @notapi + */ +static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) { + uint32_t next; + + next = usbp->pmnext; + usbp->pmnext += size; + osalDbgAssert(usbp->pmnext <= usbp->otgparams->otg_ram_size, + "OTG FIFO memory overflow"); + return next; +} + +/** + * @brief Writes to a TX FIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[in] buf buffer where to copy the endpoint data + * @param[in] n maximum number of bytes to copy + * + * @notapi + */ +static void otg_fifo_write_from_buffer(volatile uint32_t *fifop, + const uint8_t *buf, + size_t n) { + + osalDbgAssert(n > 0, "is zero"); + + while (true) { + *fifop = *((uint32_t *)buf); + if (n <= 4) { + break; + } + n -= 4; + buf += 4; + } +} + +/** + * @brief Reads a packet from the RXFIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[out] buf buffer where to copy the endpoint data + * @param[in] n number of bytes to pull from the FIFO + * @param[in] max number of bytes to copy into the buffer + * + * @notapi + */ +static void otg_fifo_read_to_buffer(volatile uint32_t *fifop, + uint8_t *buf, + size_t n, + size_t max) { + uint32_t w = 0; + size_t i = 0; + + while (i < n) { + if ((i & 3) == 0) { + w = *fifop; + } + if (i < max) { + *buf++ = (uint8_t)w; + w >>= 8; + } + i++; + } +} + +/** + * @brief Incoming packets handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_rxfifo_handler(USBDriver *usbp) { + uint32_t sts, cnt, ep; + + /* Popping the event word out of the RX FIFO.*/ + sts = usbp->otg->GRXSTSP; + + /* Event details.*/ + cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; + ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; + + switch (sts & GRXSTSP_PKTSTS_MASK) { + case GRXSTSP_SETUP_DATA: + otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf, + cnt, 8); + break; + case GRXSTSP_SETUP_COMP: + break; + case GRXSTSP_OUT_DATA: + otg_fifo_read_to_buffer(usbp->otg->FIFO[0], + usbp->epc[ep]->out_state->rxbuf, + cnt, + usbp->epc[ep]->out_state->rxsize - + usbp->epc[ep]->out_state->rxcnt); + usbp->epc[ep]->out_state->rxbuf += cnt; + usbp->epc[ep]->out_state->rxcnt += cnt; + break; + case GRXSTSP_OUT_COMP: + break; + case GRXSTSP_OUT_GLOBAL_NAK: + break; + default: + break; + } +} + +/** + * @brief Outgoing packets handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static bool otg_txfifo_handler(USBDriver *usbp, usbep_t ep) { + + /* The TXFIFO is filled until there is space and data to be transmitted.*/ + while (true) { + uint32_t n; + + /* Transaction end condition.*/ + if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) { +#if 1 + usbp->otg->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep); +#endif + return true; + } + + /* Number of bytes remaining in current transaction.*/ + n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt; + if (n > usbp->epc[ep]->in_maxsize) + n = usbp->epc[ep]->in_maxsize; + + /* Checks if in the TXFIFO there is enough space to accommodate the + next packet.*/ + if (((usbp->otg->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n) + return false; + +#if STM32_USB_OTGFIFO_FILL_BASEPRI + __set_BASEPRI(CORTEX_PRIO_MASK(STM32_USB_OTGFIFO_FILL_BASEPRI)); +#endif + otg_fifo_write_from_buffer(usbp->otg->FIFO[ep], + usbp->epc[ep]->in_state->txbuf, + n); + usbp->epc[ep]->in_state->txbuf += n; + usbp->epc[ep]->in_state->txcnt += n; +#if STM32_USB_OTGFIFO_FILL_BASEPRI + __set_BASEPRI(0); +#endif + } +} + +/** + * @brief Generic endpoint IN handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { + stm32_otg_t *otgp = usbp->otg; + uint32_t epint = otgp->ie[ep].DIEPINT; + + otgp->ie[ep].DIEPINT = epint; + + if (epint & DIEPINT_TOC) { + /* Timeouts not handled yet, not sure how to handle.*/ + } + if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) { + /* Transmit transfer complete.*/ + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + if (isp->txsize < isp->totsize) { + /* In case the transaction covered only part of the total transfer + then another transaction is immediately started in order to + cover the remaining.*/ + isp->txsize = isp->totsize - isp->txsize; + isp->txcnt = 0; + osalSysLockFromISR(); + usb_lld_start_in(usbp, ep); + osalSysUnlockFromISR(); + } + else { + /* End on IN transfer.*/ + _usb_isr_invoke_in_cb(usbp, ep); + } + } + if ((epint & DIEPINT_TXFE) && + (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) { + /* TX FIFO empty or emptying.*/ + otg_txfifo_handler(usbp, ep); + } +} + +/** + * @brief Generic endpoint OUT handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { + stm32_otg_t *otgp = usbp->otg; + uint32_t epint = otgp->oe[ep].DOEPINT; + + /* Resets all EP IRQ sources.*/ + otgp->oe[ep].DOEPINT = epint; + + if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) { + /* Setup packets handling, setup packets are handled using a + specific callback.*/ + _usb_isr_invoke_setup_cb(usbp, ep); + } + + if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) { + USBOutEndpointState *osp; + + /* OUT state structure pointer for this endpoint.*/ + osp = usbp->epc[ep]->out_state; + + /* EP0 requires special handling.*/ + if (ep == 0) { + +#if defined(STM32_OTG_SEQUENCE_WORKAROUND) + /* If an OUT transaction end interrupt is processed while the state + machine is not in an OUT state then it is ignored, this is caused + on some devices (L4) apparently injecting spurious data complete + words in the RX FIFO.*/ + if ((usbp->ep0state & USB_OUT_STATE) == 0) + return; +#endif + + /* In case the transaction covered only part of the total transfer + then another transaction is immediately started in order to + cover the remaining.*/ + if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) && + (osp->rxsize < osp->totsize)) { + osp->rxsize = osp->totsize - osp->rxsize; + osp->rxcnt = 0; + osalSysLockFromISR(); + usb_lld_start_out(usbp, ep); + osalSysUnlockFromISR(); + return; + } + } + + /* End on OUT transfer.*/ + _usb_isr_invoke_out_cb(usbp, ep); + } +} + +/** + * @brief Isochronous IN transfer failed handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_isoc_in_failed_handler(USBDriver *usbp) { + usbep_t ep; + stm32_otg_t *otgp = usbp->otg; + + for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { + if (((otgp->ie[ep].DIEPCTL & DIEPCTL_EPTYP_MASK) == DIEPCTL_EPTYP_ISO) && + ((otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) != 0)) { + /* Endpoint enabled -> ISOC IN transfer failed.*/ + /* Disable endpoint.*/ + otgp->ie[ep].DIEPCTL |= (DIEPCTL_EPDIS | DIEPCTL_SNAK); + while (otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) + ; + + /* Flush FIFO.*/ + otg_txfifo_flush(usbp, ep); + + /* Prepare data for next frame.*/ + _usb_isr_invoke_in_cb(usbp, ep); + } + } +} + +/** + * @brief Isochronous OUT transfer failed handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_isoc_out_failed_handler(USBDriver *usbp) { + usbep_t ep; + stm32_otg_t *otgp = usbp->otg; + + for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { + if (((otgp->oe[ep].DOEPCTL & DOEPCTL_EPTYP_MASK) == DOEPCTL_EPTYP_ISO) && + ((otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) != 0)) { +#if 0 + /* Endpoint enabled -> ISOC OUT transfer failed.*/ + /* Disable endpoint.*/ + /* CHTODO:: Core stucks here */ + otgp->oe[ep].DOEPCTL |= (DOEPCTL_EPDIS | DOEPCTL_SNAK); + while (otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) + ; +#endif + /* Prepare transfer for next frame.*/ + _usb_isr_invoke_out_cb(usbp, ep); + } + } +} + +/** + * @brief OTG shared ISR. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void usb_lld_serve_interrupt(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + uint32_t sts, src; + + sts = otgp->GINTSTS; + sts &= otgp->GINTMSK; + otgp->GINTSTS = sts; + + /* Reset interrupt handling.*/ + if (sts & GINTSTS_USBRST) { + /* Default reset action.*/ + _usb_reset(usbp); + + /* Preventing execution of more handlers, the core has been reset.*/ + return; + } + + /* Wake-up handling.*/ + if (sts & GINTSTS_WKUPINT) { + /* If clocks are gated off, turn them back on (may be the case if + coming out of suspend mode).*/ + if (otgp->PCGCCTL & (PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK)) { + /* Set to zero to un-gate the USB core clocks.*/ + otgp->PCGCCTL &= ~(PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK); + } + + /* Clear the Remote Wake-up Signaling.*/ + otgp->DCTL &= ~DCTL_RWUSIG; + + _usb_wakeup(usbp); + } + + /* Suspend handling.*/ + if (sts & GINTSTS_USBSUSP) { + /* Stopping all ongoing transfers.*/ + otg_disable_ep(usbp); + + /* Default suspend action.*/ + _usb_suspend(usbp); + } + + /* Enumeration done.*/ + if (sts & GINTSTS_ENUMDNE) { + /* Full or High speed timing selection.*/ + if ((otgp->DSTS & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HS_480) { + otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) | + GUSBCFG_TRDT(TRDT_VALUE_HS); + } + else { + otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) | + GUSBCFG_TRDT(TRDT_VALUE_FS); + } + } + + /* SOF interrupt handling.*/ + if (sts & GINTSTS_SOF) { + _usb_isr_invoke_sof_cb(usbp); + } + + /* Isochronous IN failed handling */ + if (sts & GINTSTS_IISOIXFR) { + otg_isoc_in_failed_handler(usbp); + } + + /* Isochronous OUT failed handling */ + if (sts & GINTSTS_IISOOXFR) { + otg_isoc_out_failed_handler(usbp); + } + + /* Performing the whole FIFO emptying in the ISR, it is advised to keep + this IRQ at a very low priority level.*/ + if ((sts & GINTSTS_RXFLVL) != 0U) { + otg_rxfifo_handler(usbp); + } + + /* IN/OUT endpoints event handling.*/ + src = otgp->DAINT; + if (sts & GINTSTS_OEPINT) { + if (src & (1 << 16)) + otg_epout_handler(usbp, 0); + if (src & (1 << 17)) + otg_epout_handler(usbp, 1); + if (src & (1 << 18)) + otg_epout_handler(usbp, 2); + if (src & (1 << 19)) + otg_epout_handler(usbp, 3); +#if USB_MAX_ENDPOINTS >= 4 + if (src & (1 << 20)) + otg_epout_handler(usbp, 4); +#endif +#if USB_MAX_ENDPOINTS >= 5 + if (src & (1 << 21)) + otg_epout_handler(usbp, 5); +#endif +#if USB_MAX_ENDPOINTS >= 6 + if (src & (1 << 22)) + otg_epout_handler(usbp, 6); +#endif +#if USB_MAX_ENDPOINTS >= 7 + if (src & (1 << 23)) + otg_epout_handler(usbp, 7); +#endif +#if USB_MAX_ENDPOINTS >= 8 + if (src & (1 << 24)) + otg_epout_handler(usbp, 8); +#endif + } + if (sts & GINTSTS_IEPINT) { + if (src & (1 << 0)) + otg_epin_handler(usbp, 0); + if (src & (1 << 1)) + otg_epin_handler(usbp, 1); + if (src & (1 << 2)) + otg_epin_handler(usbp, 2); + if (src & (1 << 3)) + otg_epin_handler(usbp, 3); +#if USB_MAX_ENDPOINTS >= 4 + if (src & (1 << 4)) + otg_epin_handler(usbp, 4); +#endif +#if USB_MAX_ENDPOINTS >= 5 + if (src & (1 << 5)) + otg_epin_handler(usbp, 5); +#endif +#if USB_MAX_ENDPOINTS >= 6 + if (src & (1 << 6)) + otg_epin_handler(usbp, 6); +#endif +#if USB_MAX_ENDPOINTS >= 7 + if (src & (1 << 7)) + otg_epin_handler(usbp, 7); +#endif +#if USB_MAX_ENDPOINTS >= 8 + if (src & (1 << 8)) + otg_epin_handler(usbp, 8); +#endif + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) +/** + * @brief OTG1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_OTG1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + usb_lld_serve_interrupt(&USBD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) +/** + * @brief OTG2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_OTG2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + usb_lld_serve_interrupt(&USBD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { + + /* Driver initialization.*/ +#if STM32_USB_USE_OTG1 + usbObjectInit(&USBD1); + USBD1.otg = OTG_FS; + USBD1.otgparams = &fsparams; + +#endif + +#if STM32_USB_USE_OTG2 + usbObjectInit(&USBD2); + USBD2.otg = OTG_HS; + USBD2.otgparams = &hsparams; +#endif +} + +/** + * @brief Configures and activates the USB peripheral. + * @note Starting the OTG cell can be a slow operation carried out with + * interrupts disabled, perform it before starting time-critical + * operations. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + if (usbp->state == USB_STOP) { + /* Clock activation.*/ + +#if STM32_USB_USE_OTG1 + if (&USBD1 == usbp) { + /* OTG FS clock enable and reset.*/ + rccEnableOTG_FS(true); + rccResetOTG_FS(); + + /* Enables IRQ vector.*/ + nvicEnableVector(STM32_OTG1_NUMBER, STM32_USB_OTG1_IRQ_PRIORITY); + + /* - Forced device mode. + - USB turn-around time = TRDT_VALUE_FS. + - Full Speed 1.1 PHY.*/ + otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) | + GUSBCFG_PHYSEL; + + /* 48MHz 1.1 PHY.*/ + otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; + } +#endif + +#if STM32_USB_USE_OTG2 + if (&USBD2 == usbp) { + /* OTG HS clock enable and reset.*/ + rccEnableOTG_HS(true); + rccResetOTG_HS(); + + /* ULPI clock is managed depending on the presence of an external + PHY.*/ +#if defined(BOARD_OTG2_USES_ULPI) + rccEnableOTG_HSULPI(true); +#else + /* Workaround for the problem described here: + http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1798.*/ + rccDisableOTG_HSULPI(); +#endif + + /* Enables IRQ vector.*/ + nvicEnableVector(STM32_OTG2_NUMBER, STM32_USB_OTG2_IRQ_PRIORITY); + + /* - Forced device mode. + - USB turn-around time = TRDT_VALUE_HS or TRDT_VALUE_FS.*/ +#if defined(BOARD_OTG2_USES_ULPI) + /* High speed ULPI PHY.*/ + otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) | + GUSBCFG_SRPCAP | GUSBCFG_HNPCAP; +#else + otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) | + GUSBCFG_PHYSEL; +#endif + +#if defined(BOARD_OTG2_USES_ULPI) +#if STM32_USE_USB_OTG2_HS + /* USB 2.0 High Speed PHY in HS mode.*/ + otgp->DCFG = 0x02200000 | DCFG_DSPD_HS; +#else + /* USB 2.0 High Speed PHY in FS mode.*/ + otgp->DCFG = 0x02200000 | DCFG_DSPD_HS_FS; +#endif +#else + /* 48MHz 1.1 PHY.*/ + otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; +#endif + } +#endif + + /* PHY enabled.*/ + otgp->PCGCCTL = 0; + + /* VBUS sensing and transceiver enabled.*/ + otgp->GOTGCTL = GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; + +#if defined(BOARD_OTG2_USES_ULPI) +#if STM32_USB_USE_OTG1 + if (&USBD1 == usbp) { + otgp->GCCFG = GCCFG_INIT_VALUE; + } +#endif + +#if STM32_USB_USE_OTG2 + if (&USBD2 == usbp) { + otgp->GCCFG = 0; + } +#endif +#else + otgp->GCCFG = GCCFG_INIT_VALUE; +#endif + + /* Soft core reset.*/ + otg_core_reset(usbp); + + /* Interrupts on TXFIFOs half empty.*/ + otgp->GAHBCFG = 0; + + /* Endpoints re-initialization.*/ + otg_disable_ep(usbp); + + /* Clear all pending Device Interrupts, only the USB Reset interrupt + is required initially.*/ + otgp->DIEPMSK = 0; + otgp->DOEPMSK = 0; + otgp->DAINTMSK = 0; + if (usbp->config->sof_cb == NULL) + otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | + GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | + GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM; + else + otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | + GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | + GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM | + GINTMSK_SOFM; + + /* Clears all pending IRQs, if any. */ + otgp->GINTSTS = 0xFFFFFFFF; + + /* Global interrupts enable.*/ + otgp->GAHBCFG |= GAHBCFG_GINTMSK; + } +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + /* If in ready state then disables the USB clock.*/ + if (usbp->state != USB_STOP) { + + /* Disabling all endpoints in case the driver has been stopped while + active.*/ + otg_disable_ep(usbp); + + otgp->DAINTMSK = 0; + otgp->GAHBCFG = 0; + otgp->GCCFG = 0; + +#if STM32_USB_USE_OTG1 + if (&USBD1 == usbp) { + nvicDisableVector(STM32_OTG1_NUMBER); + rccDisableOTG_FS(); + } +#endif + +#if STM32_USB_USE_OTG2 + if (&USBD2 == usbp) { + nvicDisableVector(STM32_OTG2_NUMBER); + rccDisableOTG_HS(); +#if defined(BOARD_OTG2_USES_ULPI) + rccDisableOTG_HSULPI() +#endif + } +#endif + } +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + unsigned i; + stm32_otg_t *otgp = usbp->otg; + + /* Flush the Tx FIFO.*/ + otg_txfifo_flush(usbp, 0); + + /* Endpoint interrupts all disabled and cleared.*/ + otgp->DIEPEMPMSK = 0; + otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); + + /* All endpoints in NAK mode, interrupts cleared.*/ + for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { + otgp->ie[i].DIEPCTL = DIEPCTL_SNAK; + otgp->oe[i].DOEPCTL = DOEPCTL_SNAK; + otgp->ie[i].DIEPINT = 0xFFFFFFFF; + otgp->oe[i].DOEPINT = 0xFFFFFFFF; + } + + /* Resets the FIFO memory allocator.*/ + otg_ram_reset(usbp); + + /* Receive FIFO size initialization, the address is always zero.*/ + otgp->GRXFSIZ = usbp->otgparams->rx_fifo_size; + otg_rxfifo_flush(usbp); + + /* Resets the device address to zero.*/ + otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0); + + /* Enables also EP-related interrupt sources.*/ + otgp->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; + otgp->DIEPMSK = DIEPMSK_TOCM | DIEPMSK_XFRCM; + otgp->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM; + + /* EP0 initialization, it is a special case.*/ + usbp->epc[0] = &ep0config; + otgp->oe[0].DOEPTSIZ = DOEPTSIZ_STUPCNT(3); + otgp->oe[0].DOEPCTL = DOEPCTL_SD0PID | DOEPCTL_USBAEP | DOEPCTL_EPTYP_CTRL | + DOEPCTL_MPSIZ(ep0config.out_maxsize); + otgp->ie[0].DIEPTSIZ = 0; + otgp->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | + DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize); + otgp->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) | + DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, + ep0config.in_maxsize / 4)); +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(usbp->address); +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + uint32_t ctl, fsize; + stm32_otg_t *otgp = usbp->otg; + + /* IN and OUT common parameters.*/ + switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) { + case USB_EP_MODE_TYPE_CTRL: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL; + break; + case USB_EP_MODE_TYPE_ISOC: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO; + break; + case USB_EP_MODE_TYPE_BULK: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK; + break; + case USB_EP_MODE_TYPE_INTR: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR; + break; + default: + return; + } + + /* OUT endpoint activation or deactivation.*/ + otgp->oe[ep].DOEPTSIZ = 0; + if (usbp->epc[ep]->out_state != NULL) { + otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize); + otgp->DAINTMSK |= DAINTMSK_OEPM(ep); + } + else { + otgp->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP; + otgp->DAINTMSK &= ~DAINTMSK_OEPM(ep); + } + + /* IN endpoint activation or deactivation.*/ + otgp->ie[ep].DIEPTSIZ = 0; + if (usbp->epc[ep]->in_state != NULL) { + /* FIFO allocation for the IN endpoint.*/ + fsize = usbp->epc[ep]->in_maxsize / 4; + if (usbp->epc[ep]->in_multiplier > 1) + fsize *= usbp->epc[ep]->in_multiplier; + otgp->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | + DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); + otg_txfifo_flush(usbp, ep); + + otgp->ie[ep].DIEPCTL = ctl | + DIEPCTL_TXFNUM(ep) | + DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize); + otgp->DAINTMSK |= DAINTMSK_IEPM(ep); + } + else { + otgp->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/ + otg_txfifo_flush(usbp, ep); + otgp->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP; + otgp->DAINTMSK &= ~DAINTMSK_IEPM(ep); + } +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + + /* Resets the FIFO memory allocator.*/ + otg_ram_reset(usbp); + + /* Disabling all endpoints.*/ + otg_disable_ep(usbp); +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + uint32_t ctl; + + (void)usbp; + + ctl = usbp->otg->oe[ep].DOEPCTL; + if (!(ctl & DOEPCTL_USBAEP)) + return EP_STATUS_DISABLED; + if (ctl & DOEPCTL_STALL) + return EP_STATUS_STALLED; + return EP_STATUS_ACTIVE; +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + uint32_t ctl; + + (void)usbp; + + ctl = usbp->otg->ie[ep].DIEPCTL; + if (!(ctl & DIEPCTL_USBAEP)) + return EP_STATUS_DISABLED; + if (ctl & DIEPCTL_STALL) + return EP_STATUS_STALLED; + return EP_STATUS_ACTIVE; +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + + memcpy(buf, usbp->epc[ep]->setup_buf, 8); +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + uint32_t pcnt, rxsize; + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + + /* Transfer initialization.*/ + osp->totsize = osp->rxsize; + if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE)) + osp->rxsize = EP0_MAX_OUTSIZE; + + /* Transaction size is rounded to a multiple of packet size because the + following requirement in the RM: + "For OUT transfers, the transfer size field in the endpoint's transfer + size register must be a multiple of the maximum packet size of the + endpoint, adjusted to the Word boundary".*/ + pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) / + usbp->epc[ep]->out_maxsize; + rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU; + + /*Setting up transaction parameters in DOEPTSIZ.*/ + usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) | + DOEPTSIZ_XFRSIZ(rxsize); + + /* Special case of isochronous endpoint.*/ + if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { + /* Odd/even bit toggling for isochronous endpoint.*/ + if (usbp->otg->DSTS & DSTS_FNSOF_ODD) + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM; + else + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM; + } + + /* Starting operation.*/ + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK; +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + /* Transfer initialization.*/ + isp->totsize = isp->txsize; + if (isp->txsize == 0) { + /* Special case, sending zero size packet.*/ + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0); + } + else { + if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE)) + isp->txsize = EP0_MAX_INSIZE; + + /* Normal case.*/ + uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / + usbp->epc[ep]->in_maxsize; + /* CHTODO: Support more than one packet per frame for isochronous transfers.*/ + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) | + DIEPTSIZ_XFRSIZ(isp->txsize); + } + + /* Special case of isochronous endpoint.*/ + if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { + /* Odd/even bit toggling.*/ + if (usbp->otg->DSTS & DSTS_FNSOF_ODD) + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SEVNFRM; + else + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM; + } + + /* Starting operation.*/ + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; + usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_STALL; +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_STALL; +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + + usbp->otg->oe[ep].DOEPCTL &= ~DOEPCTL_STALL; +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + + usbp->otg->ie[ep].DIEPCTL &= ~DIEPCTL_STALL; +} + +#endif /* HAL_USE_USB */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h b/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h index 4d7ae15935..1ccdeae2a5 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h +++ b/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h @@ -1,604 +1,604 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file OTGv1/hal_usb_lld.h - * @brief STM32 USB subsystem low level driver header. - * - * @addtogroup USB - * @{ - */ - -#ifndef HAL_USB_LLD_H -#define HAL_USB_LLD_H - -#if HAL_USE_USB || defined(__DOXYGEN__) - -#include "stm32_otg.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Status stage handling method. - */ -#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW - -/** - * @brief The address can be changed immediately upon packet reception. - */ -#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS - -/** - * @brief Method for set address acknowledge. - */ -#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief OTG1 driver enable switch. - * @details If set to @p TRUE the support for OTG_FS is included. - * @note The default is @p FALSE - */ -#if !defined(STM32_USB_USE_OTG1) || defined(__DOXYGEN__) -#define STM32_USB_USE_OTG1 FALSE -#endif - -/** - * @brief OTG2 driver enable switch. - * @details If set to @p TRUE the support for OTG_HS is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_USB_USE_OTG2) || defined(__DOXYGEN__) -#define STM32_USB_USE_OTG2 FALSE -#endif - -/** - * @brief OTG1 interrupt priority level setting. - */ -#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_OTG1_IRQ_PRIORITY 14 -#endif - -/** - * @brief OTG2 interrupt priority level setting. - */ -#if !defined(STM32_USB_OTG2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_OTG2_IRQ_PRIORITY 14 -#endif - -/** - * @brief OTG1 RX shared FIFO size. - * @note Must be a multiple of 4. - */ -#if !defined(STM32_USB_OTG1_RX_FIFO_SIZE) || defined(__DOXYGEN__) -#define STM32_USB_OTG1_RX_FIFO_SIZE 512 -#endif - -/** - * @brief OTG2 RX shared FIFO size. - * @note Must be a multiple of 4. - */ -#if !defined(STM32_USB_OTG2_RX_FIFO_SIZE) || defined(__DOXYGEN__) -#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 -#endif - -/** - * @brief Enables HS mode on OTG2 else FS mode. - * @note The default is @p TRUE. - * @note Has effect only if @p BOARD_OTG2_USES_ULPI is defined. - */ -#if !defined(STM32_USE_USB_OTG2_HS) || defined(__DOXYGEN__) -#define STM32_USE_USB_OTG2_HS TRUE -#endif - -/** - * @brief Exception priority level during TXFIFOs operations. - * @note Because an undocumented silicon behavior the operation of - * copying a packet into a TXFIFO must not be interrupted by - * any other operation on the OTG peripheral. - * This parameter represents the priority mask during copy - * operations. The default value only allows to call USB - * functions from callbacks invoked from USB ISR handlers. - * If you need to invoke USB functions from other handlers - * then raise this priority mast to the same level of the - * handler you need to use. - * @note The value zero means disabled, when disabled calling USB - * functions is only safe from thread level or from USB - * callbacks. - */ -#if !defined(STM32_USB_OTGFIFO_FILL_BASEPRI) || defined(__DOXYGEN__) -#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 -#endif - -/** - * @brief Host wake-up procedure duration. - */ -#if !defined(STM32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__) -#define STM32_USB_HOST_WAKEUP_DURATION 2 -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Registry checks.*/ -#if !defined(STM32_OTG_STEPPING) -#error "STM32_OTG_STEPPING not defined in registry" -#endif - -#if (STM32_OTG_STEPPING < 1) || (STM32_OTG_STEPPING > 2) -#error "unsupported STM32_OTG_STEPPING" -#endif - -#if !defined(STM32_HAS_OTG1) || !defined(STM32_HAS_OTG2) -#error "STM32_HAS_OTGx not defined in registry" -#endif - -#if STM32_HAS_OTG1 && !defined(STM32_OTG1_ENDPOINTS) -#error "STM32_OTG1_ENDPOINTS not defined in registry" -#endif - -#if STM32_HAS_OTG2 && !defined(STM32_OTG2_ENDPOINTS) -#error "STM32_OTG2_ENDPOINTS not defined in registry" -#endif - -#if STM32_HAS_OTG1 && !defined(STM32_OTG1_FIFO_MEM_SIZE) -#error "STM32_OTG1_FIFO_MEM_SIZE not defined in registry" -#endif - -#if STM32_HAS_OTG2 && !defined(STM32_OTG2_FIFO_MEM_SIZE) -#error "STM32_OTG2_FIFO_MEM_SIZE not defined in registry" -#endif - -#if (STM32_USB_USE_OTG1 && !defined(STM32_OTG1_HANDLER)) || \ - (STM32_USB_USE_OTG2 && !defined(STM32_OTG2_HANDLER)) -#error "STM32_OTGx_HANDLER not defined in registry" -#endif - -#if (STM32_USB_USE_OTG1 && !defined(STM32_OTG1_NUMBER)) || \ - (STM32_USB_USE_OTG2 && !defined(STM32_OTG2_NUMBER)) -#error "STM32_OTGx_NUMBER not defined in registry" -#endif - -/** - * @brief Maximum endpoint address. - */ -#if (STM32_HAS_OTG2 && STM32_USB_USE_OTG2) || defined(__DOXYGEN__) -#if (STM32_OTG1_ENDPOINTS < STM32_OTG2_ENDPOINTS) || defined(__DOXYGEN__) -#define USB_MAX_ENDPOINTS STM32_OTG2_ENDPOINTS -#else -#define USB_MAX_ENDPOINTS STM32_OTG1_ENDPOINTS -#endif -#else -#define USB_MAX_ENDPOINTS STM32_OTG1_ENDPOINTS -#endif - -#if STM32_USB_USE_OTG1 && !STM32_HAS_OTG1 -#error "OTG1 not present in the selected device" -#endif - -#if STM32_USB_USE_OTG2 && !STM32_HAS_OTG2 -#error "OTG2 not present in the selected device" -#endif - -#if !STM32_USB_USE_OTG1 && !STM32_USB_USE_OTG2 -#error "USB driver activated but no USB peripheral assigned" -#endif - -#if STM32_USB_USE_OTG1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_OTG1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OTG1" -#endif - -#if STM32_USB_USE_OTG2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_OTG2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OTG2" -#endif - -#if (STM32_USB_OTG1_RX_FIFO_SIZE & 3) != 0 -#error "OTG1 RX FIFO size must be a multiple of 4" -#endif - -#if (STM32_USB_OTG2_RX_FIFO_SIZE & 3) != 0 -#error "OTG2 RX FIFO size must be a multiple of 4" -#endif - -#if defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F7XX) -#define STM32_USBCLK STM32_PLL48CLK -#elif defined(STM32F10X_CL) -#define STM32_USBCLK STM32_OTGFSCLK -#elif defined(STM32L4XX) || defined(STM32L4XXP) -#define STM32_USBCLK STM32_48CLK -#elif defined(STM32H7XX) -/* Defines directly STM32_USBCLK.*/ -#define rccEnableOTG_FS rccEnableUSB2_OTG_FS -#define rccDisableOTG_FS rccDisableUSB2_OTG_FS -#define rccResetOTG_FS rccResetUSB2_OTG_FS -#define rccEnableOTG_HS rccEnableUSB1_OTG_HS -#define rccDisableOTG_HS rccDisableUSB1_OTG_HS -#define rccResetOTG_HS rccResetUSB1_OTG_HS -#define rccEnableOTG_HSULPI rccEnableUSB1_HSULPI -#define rccDisableOTG_HSULPI rccDisableUSB1_HSULPI -#else -#error "unsupported STM32 platform for OTG functionality" -#endif - -/* Allowing for a small tolerance.*/ -#if STM32_USBCLK < 47880000 || STM32_USBCLK > 48120000 -#error "the USB OTG driver requires a 48MHz clock" -#endif - -#if (STM32_USB_HOST_WAKEUP_DURATION < 2) || (STM32_USB_HOST_WAKEUP_DURATION > 15) -#error "invalid STM32_USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Peripheral-specific parameters block. - */ -typedef struct { - uint32_t rx_fifo_size; - uint32_t otg_ram_size; - uint32_t num_endpoints; -} stm32_otg_params_t; - -/** - * @brief Type of an IN endpoint state structure. - */ -typedef struct { - /** - * @brief Requested transmit transfer size. - */ - size_t txsize; - /** - * @brief Transmitted bytes so far. - */ - size_t txcnt; - /** - * @brief Pointer to the transmission linear buffer. - */ - const uint8_t *txbuf; -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Total transmit transfer size. - */ - size_t totsize; -} USBInEndpointState; - -/** - * @brief Type of an OUT endpoint state structure. - */ -typedef struct { - /** - * @brief Requested receive transfer size. - */ - size_t rxsize; - /** - * @brief Received bytes so far. - */ - size_t rxcnt; - /** - * @brief Pointer to the receive linear buffer. - */ - uint8_t *rxbuf; -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Total receive transfer size. - */ - size_t totsize; -} USBOutEndpointState; - -/** - * @brief Type of an USB endpoint configuration structure. - * @note Platform specific restrictions may apply to endpoints. - */ -typedef struct { - /** - * @brief Type and mode of the endpoint. - */ - uint32_t ep_mode; - /** - * @brief Setup packet notification callback. - * @details This callback is invoked when a setup packet has been - * received. - * @post The application must immediately call @p usbReadPacket() in - * order to access the received packet. - * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL - * endpoints, it should be set to @p NULL for other endpoint - * types. - */ - usbepcallback_t setup_cb; - /** - * @brief IN endpoint notification callback. - * @details This field must be set to @p NULL if callback is not required. - */ - usbepcallback_t in_cb; - /** - * @brief OUT endpoint notification callback. - * @details This field must be set to @p NULL if callback is not required. - */ - usbepcallback_t out_cb; - /** - * @brief IN endpoint maximum packet size. - * @details This field must be set to zero if the IN endpoint is not used. - */ - uint16_t in_maxsize; - /** - * @brief OUT endpoint maximum packet size. - * @details This field must be set to zero if the OUT endpoint is not used. - */ - uint16_t out_maxsize; - /** - * @brief @p USBEndpointState associated to the IN endpoint. - * @details This field must be set to @p NULL if the IN endpoint is not - * used. - */ - USBInEndpointState *in_state; - /** - * @brief @p USBEndpointState associated to the OUT endpoint. - * @details This field must be set to @p NULL if the OUT endpoint is not - * used. - */ - USBOutEndpointState *out_state; - /* End of the mandatory fields.*/ - /** - * @brief Determines the space allocated for the TXFIFO as multiples of - * the packet size (@p in_maxsize). Note that zero is interpreted - * as one for simplicity and robustness. - */ - uint16_t in_multiplier; - /** - * @brief Pointer to a buffer for setup packets. - * @details Setup packets require a dedicated 8-bytes buffer, set this - * field to @p NULL for non-control endpoints. - */ - uint8_t *setup_buf; -} USBEndpointConfig; - -/** - * @brief Type of an USB driver configuration structure. - */ -typedef struct { - /** - * @brief USB events callback. - * @details This callback is invoked when an USB driver event is registered. - */ - usbeventcb_t event_cb; - /** - * @brief Device GET_DESCRIPTOR request callback. - * @note This callback is mandatory and cannot be set to @p NULL. - */ - usbgetdescriptor_t get_descriptor_cb; - /** - * @brief Requests hook callback. - * @details This hook allows to be notified of standard requests or to - * handle non standard requests. - */ - usbreqhandler_t requests_hook_cb; - /** - * @brief Start Of Frame callback. - */ - usbcallback_t sof_cb; - /* End of the mandatory fields.*/ -} USBConfig; - -/** - * @brief Structure representing an USB driver. - */ -struct USBDriver { - /** - * @brief Driver state. - */ - usbstate_t state; - /** - * @brief Current configuration data. - */ - const USBConfig *config; - /** - * @brief Bit map of the transmitting IN endpoints. - */ - uint16_t transmitting; - /** - * @brief Bit map of the receiving OUT endpoints. - */ - uint16_t receiving; - /** - * @brief Active endpoints configurations. - */ - const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an IN endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *in_params[USB_MAX_ENDPOINTS]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an OUT endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *out_params[USB_MAX_ENDPOINTS]; - /** - * @brief Endpoint 0 state. - */ - usbep0state_t ep0state; - /** - * @brief Next position in the buffer to be transferred through endpoint 0. - */ - uint8_t *ep0next; - /** - * @brief Number of bytes yet to be transferred through endpoint 0. - */ - size_t ep0n; - /** - * @brief Endpoint 0 end transaction callback. - */ - usbcallback_t ep0endcb; - /** - * @brief Setup packet buffer. - */ - uint8_t setup[8]; - /** - * @brief Current USB device status. - */ - uint16_t status; - /** - * @brief Assigned USB address. - */ - uint8_t address; - /** - * @brief Current USB device configuration. - */ - uint8_t configuration; - /** - * @brief State of the driver when a suspend happened. - */ - usbstate_t saved_state; -#if defined(USB_DRIVER_EXT_FIELDS) - USB_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the OTG peripheral associated to this driver. - */ - stm32_otg_t *otg; - /** - * @brief Peripheral-specific parameters. - */ - const stm32_otg_params_t *otgparams; - /** - * @brief Pointer to the next address in the packet memory. - */ - uint32_t pmnext; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the exact size of a receive transaction. - * @details The received size can be different from the size specified in - * @p usbStartReceiveI() because the last packet could have a size - * different from the expected one. - * @pre The OUT endpoint must have been configured in transaction mode - * in order to use this function. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return Received data size. - * - * @notapi - */ -#define usb_lld_get_transaction_size(usbp, ep) \ - ((usbp)->epc[ep]->out_state->rxcnt) - -/** - * @brief Connects the USB device. - * - * @notapi - */ -#if (STM32_OTG_STEPPING == 1) || defined(__DOXYGEN__) -#define usb_lld_connect_bus(usbp) ((usbp)->otg->GCCFG |= GCCFG_VBUSBSEN) -#else -#define usb_lld_connect_bus(usbp) ((usbp)->otg->DCTL &= ~DCTL_SDIS) -#endif - -/** - * @brief Disconnect the USB device. - * - * @notapi - */ -#if (STM32_OTG_STEPPING == 1) || defined(__DOXYGEN__) -#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->GCCFG &= ~GCCFG_VBUSBSEN) -#else -#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->DCTL |= DCTL_SDIS) -#endif - -/** - * @brief Start of host wake-up procedure. - * - * @notapi - */ -#define usb_lld_wakeup_host(usbp) \ - do { \ - (usbp)->otg->DCTL |= DCTL_RWUSIG; \ - osalThreadSleepMilliseconds(STM32_USB_HOST_WAKEUP_DURATION); \ - (usbp)->otg->DCTL &= ~DCTL_RWUSIG; \ - } while (false) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_USB_USE_OTG1 && !defined(__DOXYGEN__) -extern USBDriver USBD1; -#endif - -#if STM32_USB_USE_OTG2 && !defined(__DOXYGEN__) -extern USBDriver USBD2; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void usb_lld_init(void); - void usb_lld_start(USBDriver *usbp); - void usb_lld_stop(USBDriver *usbp); - void usb_lld_reset(USBDriver *usbp); - void usb_lld_set_address(USBDriver *usbp); - void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); - void usb_lld_disable_endpoints(USBDriver *usbp); - usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); - usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); - void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); - void usb_lld_start_out(USBDriver *usbp, usbep_t ep); - void usb_lld_start_in(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_USB */ - -#endif /* HAL_USB_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file OTGv1/hal_usb_lld.h + * @brief STM32 USB subsystem low level driver header. + * + * @addtogroup USB + * @{ + */ + +#ifndef HAL_USB_LLD_H +#define HAL_USB_LLD_H + +#if HAL_USE_USB || defined(__DOXYGEN__) + +#include "stm32_otg.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Status stage handling method. + */ +#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW + +/** + * @brief The address can be changed immediately upon packet reception. + */ +#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS + +/** + * @brief Method for set address acknowledge. + */ +#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief OTG1 driver enable switch. + * @details If set to @p TRUE the support for OTG_FS is included. + * @note The default is @p FALSE + */ +#if !defined(STM32_USB_USE_OTG1) || defined(__DOXYGEN__) +#define STM32_USB_USE_OTG1 FALSE +#endif + +/** + * @brief OTG2 driver enable switch. + * @details If set to @p TRUE the support for OTG_HS is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_USB_USE_OTG2) || defined(__DOXYGEN__) +#define STM32_USB_USE_OTG2 FALSE +#endif + +/** + * @brief OTG1 interrupt priority level setting. + */ +#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#endif + +/** + * @brief OTG2 interrupt priority level setting. + */ +#if !defined(STM32_USB_OTG2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#endif + +/** + * @brief OTG1 RX shared FIFO size. + * @note Must be a multiple of 4. + */ +#if !defined(STM32_USB_OTG1_RX_FIFO_SIZE) || defined(__DOXYGEN__) +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#endif + +/** + * @brief OTG2 RX shared FIFO size. + * @note Must be a multiple of 4. + */ +#if !defined(STM32_USB_OTG2_RX_FIFO_SIZE) || defined(__DOXYGEN__) +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#endif + +/** + * @brief Enables HS mode on OTG2 else FS mode. + * @note The default is @p TRUE. + * @note Has effect only if @p BOARD_OTG2_USES_ULPI is defined. + */ +#if !defined(STM32_USE_USB_OTG2_HS) || defined(__DOXYGEN__) +#define STM32_USE_USB_OTG2_HS TRUE +#endif + +/** + * @brief Exception priority level during TXFIFOs operations. + * @note Because an undocumented silicon behavior the operation of + * copying a packet into a TXFIFO must not be interrupted by + * any other operation on the OTG peripheral. + * This parameter represents the priority mask during copy + * operations. The default value only allows to call USB + * functions from callbacks invoked from USB ISR handlers. + * If you need to invoke USB functions from other handlers + * then raise this priority mast to the same level of the + * handler you need to use. + * @note The value zero means disabled, when disabled calling USB + * functions is only safe from thread level or from USB + * callbacks. + */ +#if !defined(STM32_USB_OTGFIFO_FILL_BASEPRI) || defined(__DOXYGEN__) +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 +#endif + +/** + * @brief Host wake-up procedure duration. + */ +#if !defined(STM32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__) +#define STM32_USB_HOST_WAKEUP_DURATION 2 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks.*/ +#if !defined(STM32_OTG_STEPPING) +#error "STM32_OTG_STEPPING not defined in registry" +#endif + +#if (STM32_OTG_STEPPING < 1) || (STM32_OTG_STEPPING > 2) +#error "unsupported STM32_OTG_STEPPING" +#endif + +#if !defined(STM32_HAS_OTG1) || !defined(STM32_HAS_OTG2) +#error "STM32_HAS_OTGx not defined in registry" +#endif + +#if STM32_HAS_OTG1 && !defined(STM32_OTG1_ENDPOINTS) +#error "STM32_OTG1_ENDPOINTS not defined in registry" +#endif + +#if STM32_HAS_OTG2 && !defined(STM32_OTG2_ENDPOINTS) +#error "STM32_OTG2_ENDPOINTS not defined in registry" +#endif + +#if STM32_HAS_OTG1 && !defined(STM32_OTG1_FIFO_MEM_SIZE) +#error "STM32_OTG1_FIFO_MEM_SIZE not defined in registry" +#endif + +#if STM32_HAS_OTG2 && !defined(STM32_OTG2_FIFO_MEM_SIZE) +#error "STM32_OTG2_FIFO_MEM_SIZE not defined in registry" +#endif + +#if (STM32_USB_USE_OTG1 && !defined(STM32_OTG1_HANDLER)) || \ + (STM32_USB_USE_OTG2 && !defined(STM32_OTG2_HANDLER)) +#error "STM32_OTGx_HANDLER not defined in registry" +#endif + +#if (STM32_USB_USE_OTG1 && !defined(STM32_OTG1_NUMBER)) || \ + (STM32_USB_USE_OTG2 && !defined(STM32_OTG2_NUMBER)) +#error "STM32_OTGx_NUMBER not defined in registry" +#endif + +/** + * @brief Maximum endpoint address. + */ +#if (STM32_HAS_OTG2 && STM32_USB_USE_OTG2) || defined(__DOXYGEN__) +#if (STM32_OTG1_ENDPOINTS < STM32_OTG2_ENDPOINTS) || defined(__DOXYGEN__) +#define USB_MAX_ENDPOINTS STM32_OTG2_ENDPOINTS +#else +#define USB_MAX_ENDPOINTS STM32_OTG1_ENDPOINTS +#endif +#else +#define USB_MAX_ENDPOINTS STM32_OTG1_ENDPOINTS +#endif + +#if STM32_USB_USE_OTG1 && !STM32_HAS_OTG1 +#error "OTG1 not present in the selected device" +#endif + +#if STM32_USB_USE_OTG2 && !STM32_HAS_OTG2 +#error "OTG2 not present in the selected device" +#endif + +#if !STM32_USB_USE_OTG1 && !STM32_USB_USE_OTG2 +#error "USB driver activated but no USB peripheral assigned" +#endif + +#if STM32_USB_USE_OTG1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_OTG1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OTG1" +#endif + +#if STM32_USB_USE_OTG2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_OTG2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OTG2" +#endif + +#if (STM32_USB_OTG1_RX_FIFO_SIZE & 3) != 0 +#error "OTG1 RX FIFO size must be a multiple of 4" +#endif + +#if (STM32_USB_OTG2_RX_FIFO_SIZE & 3) != 0 +#error "OTG2 RX FIFO size must be a multiple of 4" +#endif + +#if defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F7XX) +#define STM32_USBCLK STM32_PLL48CLK +#elif defined(STM32F10X_CL) +#define STM32_USBCLK STM32_OTGFSCLK +#elif defined(STM32L4XX) || defined(STM32L4XXP) +#define STM32_USBCLK STM32_48CLK +#elif defined(STM32H7XX) +/* Defines directly STM32_USBCLK.*/ +#define rccEnableOTG_FS rccEnableUSB2_OTG_FS +#define rccDisableOTG_FS rccDisableUSB2_OTG_FS +#define rccResetOTG_FS rccResetUSB2_OTG_FS +#define rccEnableOTG_HS rccEnableUSB1_OTG_HS +#define rccDisableOTG_HS rccDisableUSB1_OTG_HS +#define rccResetOTG_HS rccResetUSB1_OTG_HS +#define rccEnableOTG_HSULPI rccEnableUSB1_HSULPI +#define rccDisableOTG_HSULPI rccDisableUSB1_HSULPI +#else +#error "unsupported STM32 platform for OTG functionality" +#endif + +/* Allowing for a small tolerance.*/ +#if STM32_USBCLK < 47880000 || STM32_USBCLK > 48120000 +#error "the USB OTG driver requires a 48MHz clock" +#endif + +#if (STM32_USB_HOST_WAKEUP_DURATION < 2) || (STM32_USB_HOST_WAKEUP_DURATION > 15) +#error "invalid STM32_USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Peripheral-specific parameters block. + */ +typedef struct { + uint32_t rx_fifo_size; + uint32_t otg_ram_size; + uint32_t num_endpoints; +} stm32_otg_params_t; + +/** + * @brief Type of an IN endpoint state structure. + */ +typedef struct { + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; + /** + * @brief Pointer to the transmission linear buffer. + */ + const uint8_t *txbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Total transmit transfer size. + */ + size_t totsize; +} USBInEndpointState; + +/** + * @brief Type of an OUT endpoint state structure. + */ +typedef struct { + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; + /** + * @brief Pointer to the receive linear buffer. + */ + uint8_t *rxbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Total receive transfer size. + */ + size_t totsize; +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if callback is not required. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if callback is not required. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ + /** + * @brief Determines the space allocated for the TXFIFO as multiples of + * the packet size (@p in_maxsize). Note that zero is interpreted + * as one for simplicity and robustness. + */ + uint16_t in_multiplier; + /** + * @brief Pointer to a buffer for setup packets. + * @details Setup packets require a dedicated 8-bytes buffer, set this + * field to @p NULL for non-control endpoints. + */ + uint8_t *setup_buf; +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an IN endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *in_params[USB_MAX_ENDPOINTS]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an OUT endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *out_params[USB_MAX_ENDPOINTS]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; + /** + * @brief State of the driver when a suspend happened. + */ + usbstate_t saved_state; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the OTG peripheral associated to this driver. + */ + stm32_otg_t *otg; + /** + * @brief Peripheral-specific parameters. + */ + const stm32_otg_params_t *otgparams; + /** + * @brief Pointer to the next address in the packet memory. + */ + uint32_t pmnext; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +/** + * @brief Connects the USB device. + * + * @notapi + */ +#if (STM32_OTG_STEPPING == 1) || defined(__DOXYGEN__) +#define usb_lld_connect_bus(usbp) ((usbp)->otg->GCCFG |= GCCFG_VBUSBSEN) +#else +#define usb_lld_connect_bus(usbp) ((usbp)->otg->DCTL &= ~DCTL_SDIS) +#endif + +/** + * @brief Disconnect the USB device. + * + * @notapi + */ +#if (STM32_OTG_STEPPING == 1) || defined(__DOXYGEN__) +#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->GCCFG &= ~GCCFG_VBUSBSEN) +#else +#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->DCTL |= DCTL_SDIS) +#endif + +/** + * @brief Start of host wake-up procedure. + * + * @notapi + */ +#define usb_lld_wakeup_host(usbp) \ + do { \ + (usbp)->otg->DCTL |= DCTL_RWUSIG; \ + osalThreadSleepMilliseconds(STM32_USB_HOST_WAKEUP_DURATION); \ + (usbp)->otg->DCTL &= ~DCTL_RWUSIG; \ + } while (false) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 && !defined(__DOXYGEN__) +extern USBDriver USBD1; +#endif + +#if STM32_USB_USE_OTG2 && !defined(__DOXYGEN__) +extern USBDriver USBD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB */ + +#endif /* HAL_USB_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h b/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h index 0ea7314053..c093470f10 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h +++ b/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h @@ -1,927 +1,927 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file OTGv1/stm32_otg.h - * @brief STM32 OTG registers layout header. - * - * @addtogroup USB - * @{ - */ - -#ifndef STM32_OTG_H -#define STM32_OTG_H - -/** - * @brief OTG_FS FIFO memory size in words. - */ -#define STM32_OTG1_FIFO_MEM_SIZE 320 - -/** - * @brief OTG_HS FIFO memory size in words. - */ -#define STM32_OTG2_FIFO_MEM_SIZE 1024 - -/** - * @brief Host channel registers group. - */ -typedef struct { - volatile uint32_t HCCHAR; /**< @brief Host channel characteristics - register. */ - volatile uint32_t resvd8; - volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/ - volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask - register. */ - volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size - register. */ - volatile uint32_t resvd14; - volatile uint32_t resvd18; - volatile uint32_t resvd1c; -} stm32_otg_host_chn_t; - -/** - * @brief Device input endpoint registers group. - */ -typedef struct { - volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint - control register. */ - volatile uint32_t resvd4; - volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt - register. */ - volatile uint32_t resvdC; - volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size - register. */ - volatile uint32_t resvd14; - volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO - status register. */ - volatile uint32_t resvd1C; -} stm32_otg_in_ep_t; - -/** - * @brief Device output endpoint registers group. - */ -typedef struct { - volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint - control register. */ - volatile uint32_t resvd4; - volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt - register. */ - volatile uint32_t resvdC; - volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer - size register. */ - volatile uint32_t resvd14; - volatile uint32_t resvd18; - volatile uint32_t resvd1C; -} stm32_otg_out_ep_t; - -/** - * @brief USB registers memory map. - */ -typedef struct { - volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/ - volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */ - volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */ - volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */ - volatile uint32_t GRSTCTL; /**< @brief Reset register size. */ - volatile uint32_t GINTSTS; /**< @brief Interrupt register. */ - volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */ - volatile uint32_t GRXSTSR; /**< @brief Receive status debug read - register. */ - volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop - register. */ - volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */ - volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size - register. */ - volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue - status register. */ - volatile uint32_t resvd30; - volatile uint32_t resvd34; - volatile uint32_t GCCFG; /**< @brief General core configuration. */ - volatile uint32_t CID; /**< @brief Core ID register. */ - volatile uint32_t resvd58[48]; - volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size - register. */ - volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO - size registers. */ - volatile uint32_t resvd140[176]; - volatile uint32_t HCFG; /**< @brief Host configuration register. */ - volatile uint32_t HFIR; /**< @brief Host frame interval register. */ - volatile uint32_t HFNUM; /**< @brief Host frame number/frame time - Remaining register. */ - volatile uint32_t resvd40C; - volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue - status register. */ - volatile uint32_t HAINT; /**< @brief Host all channels interrupt - register. */ - volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask - register. */ - volatile uint32_t resvd41C[9]; - volatile uint32_t HPRT; /**< @brief Host port control and status - register. */ - volatile uint32_t resvd444[47]; - stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */ - volatile uint32_t resvd700[64]; - volatile uint32_t DCFG; /**< @brief Device configuration register. */ - volatile uint32_t DCTL; /**< @brief Device control register. */ - volatile uint32_t DSTS; /**< @brief Device status register. */ - volatile uint32_t resvd80C; - volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common - interrupt mask register. */ - volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common - interrupt mask register. */ - volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt - register. */ - volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt - mask register. */ - volatile uint32_t resvd820; - volatile uint32_t resvd824; - volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time - register. */ - volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time - register. */ - volatile uint32_t resvd830; - volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty - interrupt mask register. */ - volatile uint32_t resvd838; - volatile uint32_t resvd83C; - volatile uint32_t resvd840[16]; - volatile uint32_t resvd880[16]; - volatile uint32_t resvd8C0[16]; - stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */ - stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */ - volatile uint32_t resvdD00[64]; - volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control - register. */ - volatile uint32_t resvdE04[127]; - volatile uint32_t FIFO[16][1024]; -} stm32_otg_t; - -/** - * @name GOTGCTL register bit definitions - * @{ - */ -#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */ -#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */ -#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */ -#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */ -#define GOTGCTL_EHEN (1U<<12) -#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */ -#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */ -#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */ -#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */ -#define GOTGCTL_BVALOVAL (1U<<7) -#define GOTGCTL_BVALOEN (1U<<6) -#define GOTGCTL_AVALOVAL (1U<<5) -#define GOTGCTL_AVALOEN (1U<<4) -#define GOTGCTL_VBVALOVAL (1U<<3) -#define GOTGCTL_VBVALOEN (1U<<2) -#define GOTGCTL_SRQ (1U<<1) /**< Session request. */ -#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */ -/** @} */ - -/** - * @name GOTGINT register bit definitions - * @{ - */ -#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */ -#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */ -#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */ -#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success - status change. */ -#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success - status change. */ -#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */ -/** @} */ - -/** - * @name GAHBCFG register bit definitions - * @{ - */ -#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty - level. */ -#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty - level. */ -#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */ -#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS - only). */ -#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS - only). */ -#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */ -/** @} */ - -/** - * @name GUSBCFG register bit definitions - * @{ - */ -#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */ -#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */ -#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */ -#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field - mask. */ -#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field - value. */ -#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */ -#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */ -#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or - USB 1.1 Full-Speed serial - transceiver Select. */ -#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration - field mask. */ -#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration - field value. */ -/** @} */ - -/** - * @name GRSTCTL register bit definitions - * @{ - */ -#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */ -#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */ -#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */ -#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */ -#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */ -#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */ -#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */ -#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */ -/** @} */ - -/** - * @name GINTSTS register bit definitions - * @{ - */ -#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup - detected interrupt. */ -#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session - detected interrupt. */ -#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected - interrupt. */ -#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/ -#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */ -#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */ -#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */ -#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic - transfer. */ -#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT - transfer. */ -#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN - transfer. */ -#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */ -#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */ -#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame - interrupt. */ -#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet - dropped interrupt. */ -#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */ -#define GINTSTS_USBRST (1U<<12) /**< USB reset. */ -#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */ -#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */ -#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */ -#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK - effective. */ -#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */ -#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */ -#define GINTSTS_SOF (1U<<3) /**< Start of frame. */ -#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */ -#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */ -#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */ -/** @} */ - -/** - * @name GINTMSK register bit definitions - * @{ - */ -#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup - detected interrupt mask. */ -#define GINTMSK_SRQM (1U<<30) /**< Session request/New session - detected interrupt mask. */ -#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected - interrupt mask. */ -#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change - mask. */ -#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/ -#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt - mask. */ -#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */ -#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic - transfer mask. */ -#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT - transfer mask. */ -#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN - transfer mask. */ -#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt - mask. */ -#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt - mask. */ -#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame - interrupt mask. */ -#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet - dropped interrupt mask. */ -#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */ -#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */ -#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */ -#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */ -#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective - mask. */ -#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK - effective mask. */ -#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty - mask. */ -#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty - mask. */ -#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/ -#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */ -#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt - mask. */ -/** @} */ - -/** - * @name GRXSTSR register bit definitions - * @{ - */ -#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */ -#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */ -#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1) -#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2) -#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3) -#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4) -#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6) -#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */ -#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */ -#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ -#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */ -#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */ -#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */ -#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ -#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ -/** @} */ - -/** - * @name GRXSTSP register bit definitions - * @{ - */ -#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */ -#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */ -#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1) -#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2) -#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3) -#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4) -#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6) -#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */ -#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */ -#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ -#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */ -#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */ -#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */ -#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */ -#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ -#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */ -#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ -/** @} */ - -/** - * @name GRXFSIZ register bit definitions - * @{ - */ -#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */ -#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */ -/** @} */ - -/** - * @name DIEPTXFx register bit definitions - * @{ - */ -#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth - mask. */ -#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth - value. */ -#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit - RAM start address mask. */ -#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit - RAM start address value. */ -/** @} */ - -/** - * @name GCCFG register bit definitions - * @{ - */ -/* Definitions for stepping 1.*/ -#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */ -#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */ -#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B" - device. */ -#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A" - device. */ - -/* Definitions for stepping 2.*/ -#define GCCFG_VBDEN (1U<<21) /**< VBUS sensing enable. */ -#define GCCFG_PWRDWN (1U<<16) /**< Power down. */ -/** @} */ - -/** - * @name HPTXFSIZ register bit definitions - * @{ - */ -#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO - depth mask. */ -#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO - depth value. */ -#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO - Start address mask. */ -#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO - start address value. */ -/** @} */ - -/** - * @name HCFG register bit definitions - * @{ - */ -#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */ -#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select - mask. */ -#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at - 48 MHz. */ -#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at - 6 MHz. */ -/** @} */ - -/** - * @name HFIR register bit definitions - * @{ - */ -#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */ -#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */ -/** @} */ - -/** - * @name HFNUM register bit definitions - * @{ - */ -#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/ -#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/ -#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */ -#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */ -/** @} */ - -/** - * @name HPTXSTS register bit definitions - * @{ - */ -#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic - transmit request queue - mask. */ -#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic - transmit request queue - value. */ -#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request - queue Space Available - mask. */ -#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request - queue Space Available - value. */ -#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data - FIFO Space Available - mask. */ -#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data - FIFO Space Available - value. */ -/** @} */ - -/** - * @name HAINT register bit definitions - * @{ - */ -#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */ -#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */ -/** @} */ - -/** - * @name HAINTMSK register bit definitions - * @{ - */ -#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask - mask. */ -#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask - value. */ -/** @} */ - -/** - * @name HPRT register bit definitions - * @{ - */ -#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */ -#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */ -#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */ -#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */ -#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */ -#define HPRT_PPWR (1U<<12) /**< Port power. */ -#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */ -#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */ -#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */ -#define HPRT_PRST (1U<<8) /**< Port reset. */ -#define HPRT_PSUSP (1U<<7) /**< Port suspend. */ -#define HPRT_PRES (1U<<6) /**< Port Resume. */ -#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */ -#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */ -#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/ -#define HPRT_PENA (1U<<2) /**< Port enable. */ -#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */ -#define HPRT_PCSTS (1U<<0) /**< Port connect status. */ -/** @} */ - -/** - * @name HCCHAR register bit definitions - * @{ - */ -#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */ -#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */ -#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */ -#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */ -#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */ -#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */ -#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */ -#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ -#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */ -#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */ -#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/ -#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */ -#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */ -#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */ -#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */ -#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */ -#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */ -#define HCCHAR_MPS_MASK (0x7FFU<<0) /**< Maximum packet size mask. */ -#define HCCHAR_MPS(n) ((n)<<0) /**< Maximum packet size value. */ -/** @} */ - -/** - * @name HCINT register bit definitions - * @{ - */ -#define HCINT_DTERR (1U<<10) /**< Data toggle error. */ -#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */ -#define HCINT_BBERR (1U<<8) /**< Babble error. */ -#define HCINT_TRERR (1U<<7) /**< Transaction Error. */ -#define HCINT_ACK (1U<<5) /**< ACK response - received/transmitted - interrupt. */ -#define HCINT_NAK (1U<<4) /**< NAK response received - interrupt. */ -#define HCINT_STALL (1U<<3) /**< STALL response received - interrupt. */ -#define HCINT_AHBERR (1U<<2) /**< AHB error interrupt. */ -#define HCINT_CHH (1U<<1) /**< Channel halted. */ -#define HCINT_XFRC (1U<<0) /**< Transfer completed. */ -/** @} */ - -/** - * @name HCINTMSK register bit definitions - * @{ - */ -#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */ -#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */ -#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */ -#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */ -#define HCINTMSK_NYET (1U<<6) /**< NYET response received - interrupt mask. */ -#define HCINTMSK_ACKM (1U<<5) /**< ACK Response - received/transmitted - interrupt mask. */ -#define HCINTMSK_NAKM (1U<<4) /**< NAK response received - interrupt mask. */ -#define HCINTMSK_STALLM (1U<<3) /**< STALL response received - interrupt mask. */ -#define HCINTMSK_AHBERRM (1U<<2) /**< AHB error interrupt mask. */ -#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */ -#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */ -/** @} */ - -/** - * @name HCTSIZ register bit definitions - * @{ - */ -#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */ -#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */ -#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */ -#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */ -#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */ -#define HCTSIZ_DPID_SETUP (3U<<29) /**< SETUP. */ -#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ -#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */ -#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name DCFG register bit definitions - * @{ - */ -#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval - mask. */ -#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval - value. */ -#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */ -#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */ -#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status - OUT handshake. */ -#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */ -#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */ -#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS - mode. */ -#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1 - transceiver clock is 48 - MHz). */ -/** @} */ - -/** - * @name DCTL register bit definitions - * @{ - */ -#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */ -#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */ -#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */ -#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic - IN NAK. */ -#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic - IN NAK. */ -#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */ -#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */ -#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */ -#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN - NAK status. */ -#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */ -#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */ -/** @} */ - -/** - * @name DSTS register bit definitions - * @{ - */ -#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received - SOF mask. */ -#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received - SOF value. */ -#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received - SOF value. */ -#define DSTS_EERR (1U<<3) /**< Erratic error. */ -#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */ -#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is - running at 48 MHz). */ -#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed. */ -#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */ -/** @} */ - -/** - * @name DIEPMSK register bit definitions - * @{ - */ -#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */ -#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective - mask. */ -#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when - TxFIFO empty mask. */ -#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */ -#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled - interrupt mask. */ -#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed - interrupt mask. */ -/** @} */ - -/** - * @name DOEPMSK register bit definitions - * @{ - */ -#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when - endpoint disabled mask. */ -#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */ -#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled - interrupt mask. */ -#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed - interrupt mask. */ -/** @} */ - -/** - * @name DAINT register bit definitions - * @{ - */ -#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt - bits mask. */ -#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt - bits value. */ -#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt - bits mask. */ -#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt - bits value. */ -/** @} */ - -/** - * @name DAINTMSK register bit definitions - * @{ - */ -#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask - bits mask. */ -#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask - bits value. */ -#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask - bits mask. */ -#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask - bits value. */ -/** @} */ - -/** - * @name DVBUSDIS register bit definitions - * @{ - */ -#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge - time mask. */ -#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge - time value. */ -/** @} */ - -/** - * @name DVBUSPULSE register bit definitions - * @{ - */ -#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time - mask. */ -#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time - value. */ -/** @} */ - -/** - * @name DIEPEMPMSK register bit definitions - * @{ - */ -#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty - interrupt mask bit. */ -/** @} */ - -/** - * @name DIEPCTL register bit definitions - * @{ - */ -#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ -#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ -#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ -#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ -#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ -#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ -#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */ -#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */ -#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */ -#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */ -#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */ -#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */ -#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */ -#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ -#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ -#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ -#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ -#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */ -#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ -#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ -#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ -#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ -#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ -/** @} */ - -/** - * @name DIEPINT register bit definitions - * @{ - */ -#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */ -#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */ -#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when - TxFIFO is empty. */ -#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */ -#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled - interrupt. */ -#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */ -/** @} */ - -/** - * @name DIEPTSIZ register bit definitions - * @{ - */ -#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */ -#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */ -#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */ -#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ -#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name DTXFSTS register bit definitions. - * @{ - */ -#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space - available. */ -/** @} */ - -/** - * @name DOEPCTL register bit definitions. - * @{ - */ -#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ -#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ -#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ -#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ -#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ -#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ -#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */ -#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */ -#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */ -#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */ -#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ -#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ -#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ -#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ -#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ -#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */ -#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ -#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ -#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ -#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ -#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ -/** @} */ - -/** - * @name DOEPINT register bit definitions - * @{ - */ -#define DOEPINT_SETUP_RCVD (1U<<15) /**< SETUP packet received. */ -#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets - received. */ -#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when - endpoint disabled. */ -#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */ -#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled - interrupt. */ -#define DOEPINT_XFRC (1U<<0) /**< Transfer completed - interrupt. */ -/** @} */ - -/** - * @name DOEPTSIZ register bit definitions - * @{ - */ -#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */ -#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */ -#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */ -#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */ -#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ -#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ -#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name PCGCCTL register bit definitions - * @{ - */ -#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */ -#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */ -#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */ -/** @} */ - -#if defined(STM32H7XX) || defined(__DOXYGEN__) -/** - * @brief OTG_FS registers block memory address. - */ -#define OTG_FS_ADDR 0x40080000 - -/** - * @brief OTG_HS registers block memory address. - */ -#define OTG_HS_ADDR 0x40040000 -#else -#define OTG_FS_ADDR 0x50000000 -#define OTG_HS_ADDR 0x40040000 -#endif - -/** - * @brief Accesses to the OTG_FS registers block. - */ -#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR) - -/** - * @brief Accesses to the OTG_HS registers block. - */ -#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR) - -#endif /* STM32_OTG_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file OTGv1/stm32_otg.h + * @brief STM32 OTG registers layout header. + * + * @addtogroup USB + * @{ + */ + +#ifndef STM32_OTG_H +#define STM32_OTG_H + +/** + * @brief OTG_FS FIFO memory size in words. + */ +#define STM32_OTG1_FIFO_MEM_SIZE 320 + +/** + * @brief OTG_HS FIFO memory size in words. + */ +#define STM32_OTG2_FIFO_MEM_SIZE 1024 + +/** + * @brief Host channel registers group. + */ +typedef struct { + volatile uint32_t HCCHAR; /**< @brief Host channel characteristics + register. */ + volatile uint32_t resvd8; + volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/ + volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask + register. */ + volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size + register. */ + volatile uint32_t resvd14; + volatile uint32_t resvd18; + volatile uint32_t resvd1c; +} stm32_otg_host_chn_t; + +/** + * @brief Device input endpoint registers group. + */ +typedef struct { + volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint + control register. */ + volatile uint32_t resvd4; + volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt + register. */ + volatile uint32_t resvdC; + volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size + register. */ + volatile uint32_t resvd14; + volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO + status register. */ + volatile uint32_t resvd1C; +} stm32_otg_in_ep_t; + +/** + * @brief Device output endpoint registers group. + */ +typedef struct { + volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint + control register. */ + volatile uint32_t resvd4; + volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt + register. */ + volatile uint32_t resvdC; + volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer + size register. */ + volatile uint32_t resvd14; + volatile uint32_t resvd18; + volatile uint32_t resvd1C; +} stm32_otg_out_ep_t; + +/** + * @brief USB registers memory map. + */ +typedef struct { + volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/ + volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */ + volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */ + volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */ + volatile uint32_t GRSTCTL; /**< @brief Reset register size. */ + volatile uint32_t GINTSTS; /**< @brief Interrupt register. */ + volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */ + volatile uint32_t GRXSTSR; /**< @brief Receive status debug read + register. */ + volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop + register. */ + volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */ + volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size + register. */ + volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue + status register. */ + volatile uint32_t resvd30; + volatile uint32_t resvd34; + volatile uint32_t GCCFG; /**< @brief General core configuration. */ + volatile uint32_t CID; /**< @brief Core ID register. */ + volatile uint32_t resvd58[48]; + volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size + register. */ + volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO + size registers. */ + volatile uint32_t resvd140[176]; + volatile uint32_t HCFG; /**< @brief Host configuration register. */ + volatile uint32_t HFIR; /**< @brief Host frame interval register. */ + volatile uint32_t HFNUM; /**< @brief Host frame number/frame time + Remaining register. */ + volatile uint32_t resvd40C; + volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue + status register. */ + volatile uint32_t HAINT; /**< @brief Host all channels interrupt + register. */ + volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask + register. */ + volatile uint32_t resvd41C[9]; + volatile uint32_t HPRT; /**< @brief Host port control and status + register. */ + volatile uint32_t resvd444[47]; + stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */ + volatile uint32_t resvd700[64]; + volatile uint32_t DCFG; /**< @brief Device configuration register. */ + volatile uint32_t DCTL; /**< @brief Device control register. */ + volatile uint32_t DSTS; /**< @brief Device status register. */ + volatile uint32_t resvd80C; + volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common + interrupt mask register. */ + volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common + interrupt mask register. */ + volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt + register. */ + volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt + mask register. */ + volatile uint32_t resvd820; + volatile uint32_t resvd824; + volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time + register. */ + volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time + register. */ + volatile uint32_t resvd830; + volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty + interrupt mask register. */ + volatile uint32_t resvd838; + volatile uint32_t resvd83C; + volatile uint32_t resvd840[16]; + volatile uint32_t resvd880[16]; + volatile uint32_t resvd8C0[16]; + stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */ + stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */ + volatile uint32_t resvdD00[64]; + volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control + register. */ + volatile uint32_t resvdE04[127]; + volatile uint32_t FIFO[16][1024]; +} stm32_otg_t; + +/** + * @name GOTGCTL register bit definitions + * @{ + */ +#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */ +#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */ +#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */ +#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */ +#define GOTGCTL_EHEN (1U<<12) +#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */ +#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */ +#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */ +#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */ +#define GOTGCTL_BVALOVAL (1U<<7) +#define GOTGCTL_BVALOEN (1U<<6) +#define GOTGCTL_AVALOVAL (1U<<5) +#define GOTGCTL_AVALOEN (1U<<4) +#define GOTGCTL_VBVALOVAL (1U<<3) +#define GOTGCTL_VBVALOEN (1U<<2) +#define GOTGCTL_SRQ (1U<<1) /**< Session request. */ +#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */ +/** @} */ + +/** + * @name GOTGINT register bit definitions + * @{ + */ +#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */ +#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */ +#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */ +#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success + status change. */ +#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success + status change. */ +#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */ +/** @} */ + +/** + * @name GAHBCFG register bit definitions + * @{ + */ +#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty + level. */ +#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty + level. */ +#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */ +#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS + only). */ +#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS + only). */ +#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */ +/** @} */ + +/** + * @name GUSBCFG register bit definitions + * @{ + */ +#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */ +#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */ +#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */ +#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field + mask. */ +#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field + value. */ +#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */ +#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */ +#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or + USB 1.1 Full-Speed serial + transceiver Select. */ +#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration + field mask. */ +#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration + field value. */ +/** @} */ + +/** + * @name GRSTCTL register bit definitions + * @{ + */ +#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */ +#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */ +#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */ +#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */ +#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */ +#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */ +#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */ +#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */ +/** @} */ + +/** + * @name GINTSTS register bit definitions + * @{ + */ +#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup + detected interrupt. */ +#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session + detected interrupt. */ +#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected + interrupt. */ +#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/ +#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */ +#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */ +#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */ +#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic + transfer. */ +#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT + transfer. */ +#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN + transfer. */ +#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */ +#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */ +#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame + interrupt. */ +#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet + dropped interrupt. */ +#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */ +#define GINTSTS_USBRST (1U<<12) /**< USB reset. */ +#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */ +#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */ +#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */ +#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK + effective. */ +#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */ +#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */ +#define GINTSTS_SOF (1U<<3) /**< Start of frame. */ +#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */ +#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */ +#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */ +/** @} */ + +/** + * @name GINTMSK register bit definitions + * @{ + */ +#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup + detected interrupt mask. */ +#define GINTMSK_SRQM (1U<<30) /**< Session request/New session + detected interrupt mask. */ +#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected + interrupt mask. */ +#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change + mask. */ +#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/ +#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt + mask. */ +#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */ +#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic + transfer mask. */ +#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT + transfer mask. */ +#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN + transfer mask. */ +#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt + mask. */ +#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt + mask. */ +#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame + interrupt mask. */ +#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet + dropped interrupt mask. */ +#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */ +#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */ +#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */ +#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */ +#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective + mask. */ +#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK + effective mask. */ +#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty + mask. */ +#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty + mask. */ +#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/ +#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */ +#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt + mask. */ +/** @} */ + +/** + * @name GRXSTSR register bit definitions + * @{ + */ +#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */ +#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */ +#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1) +#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2) +#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3) +#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4) +#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6) +#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */ +#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */ +#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ +#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */ +#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */ +#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */ +#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ +#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ +/** @} */ + +/** + * @name GRXSTSP register bit definitions + * @{ + */ +#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */ +#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */ +#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1) +#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2) +#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3) +#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4) +#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6) +#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */ +#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */ +#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ +#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */ +#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */ +#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */ +#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */ +#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ +#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */ +#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ +/** @} */ + +/** + * @name GRXFSIZ register bit definitions + * @{ + */ +#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */ +#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */ +/** @} */ + +/** + * @name DIEPTXFx register bit definitions + * @{ + */ +#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth + mask. */ +#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth + value. */ +#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit + RAM start address mask. */ +#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit + RAM start address value. */ +/** @} */ + +/** + * @name GCCFG register bit definitions + * @{ + */ +/* Definitions for stepping 1.*/ +#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */ +#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */ +#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B" + device. */ +#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A" + device. */ + +/* Definitions for stepping 2.*/ +#define GCCFG_VBDEN (1U<<21) /**< VBUS sensing enable. */ +#define GCCFG_PWRDWN (1U<<16) /**< Power down. */ +/** @} */ + +/** + * @name HPTXFSIZ register bit definitions + * @{ + */ +#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO + depth mask. */ +#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO + depth value. */ +#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO + Start address mask. */ +#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO + start address value. */ +/** @} */ + +/** + * @name HCFG register bit definitions + * @{ + */ +#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */ +#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select + mask. */ +#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at + 48 MHz. */ +#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at + 6 MHz. */ +/** @} */ + +/** + * @name HFIR register bit definitions + * @{ + */ +#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */ +#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */ +/** @} */ + +/** + * @name HFNUM register bit definitions + * @{ + */ +#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/ +#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/ +#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */ +#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */ +/** @} */ + +/** + * @name HPTXSTS register bit definitions + * @{ + */ +#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic + transmit request queue + mask. */ +#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic + transmit request queue + value. */ +#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request + queue Space Available + mask. */ +#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request + queue Space Available + value. */ +#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data + FIFO Space Available + mask. */ +#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data + FIFO Space Available + value. */ +/** @} */ + +/** + * @name HAINT register bit definitions + * @{ + */ +#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */ +#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */ +/** @} */ + +/** + * @name HAINTMSK register bit definitions + * @{ + */ +#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask + mask. */ +#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask + value. */ +/** @} */ + +/** + * @name HPRT register bit definitions + * @{ + */ +#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */ +#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */ +#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */ +#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */ +#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */ +#define HPRT_PPWR (1U<<12) /**< Port power. */ +#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */ +#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */ +#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */ +#define HPRT_PRST (1U<<8) /**< Port reset. */ +#define HPRT_PSUSP (1U<<7) /**< Port suspend. */ +#define HPRT_PRES (1U<<6) /**< Port Resume. */ +#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */ +#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */ +#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/ +#define HPRT_PENA (1U<<2) /**< Port enable. */ +#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */ +#define HPRT_PCSTS (1U<<0) /**< Port connect status. */ +/** @} */ + +/** + * @name HCCHAR register bit definitions + * @{ + */ +#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */ +#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */ +#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */ +#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */ +#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */ +#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */ +#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */ +#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ +#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */ +#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */ +#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/ +#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */ +#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */ +#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */ +#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */ +#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */ +#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */ +#define HCCHAR_MPS_MASK (0x7FFU<<0) /**< Maximum packet size mask. */ +#define HCCHAR_MPS(n) ((n)<<0) /**< Maximum packet size value. */ +/** @} */ + +/** + * @name HCINT register bit definitions + * @{ + */ +#define HCINT_DTERR (1U<<10) /**< Data toggle error. */ +#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */ +#define HCINT_BBERR (1U<<8) /**< Babble error. */ +#define HCINT_TRERR (1U<<7) /**< Transaction Error. */ +#define HCINT_ACK (1U<<5) /**< ACK response + received/transmitted + interrupt. */ +#define HCINT_NAK (1U<<4) /**< NAK response received + interrupt. */ +#define HCINT_STALL (1U<<3) /**< STALL response received + interrupt. */ +#define HCINT_AHBERR (1U<<2) /**< AHB error interrupt. */ +#define HCINT_CHH (1U<<1) /**< Channel halted. */ +#define HCINT_XFRC (1U<<0) /**< Transfer completed. */ +/** @} */ + +/** + * @name HCINTMSK register bit definitions + * @{ + */ +#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */ +#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */ +#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */ +#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */ +#define HCINTMSK_NYET (1U<<6) /**< NYET response received + interrupt mask. */ +#define HCINTMSK_ACKM (1U<<5) /**< ACK Response + received/transmitted + interrupt mask. */ +#define HCINTMSK_NAKM (1U<<4) /**< NAK response received + interrupt mask. */ +#define HCINTMSK_STALLM (1U<<3) /**< STALL response received + interrupt mask. */ +#define HCINTMSK_AHBERRM (1U<<2) /**< AHB error interrupt mask. */ +#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */ +#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */ +/** @} */ + +/** + * @name HCTSIZ register bit definitions + * @{ + */ +#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */ +#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */ +#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */ +#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */ +#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */ +#define HCTSIZ_DPID_SETUP (3U<<29) /**< SETUP. */ +#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ +#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ +#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */ +#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ +/** @} */ + +/** + * @name DCFG register bit definitions + * @{ + */ +#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval + mask. */ +#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval + value. */ +#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */ +#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */ +#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status + OUT handshake. */ +#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */ +#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */ +#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS + mode. */ +#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1 + transceiver clock is 48 + MHz). */ +/** @} */ + +/** + * @name DCTL register bit definitions + * @{ + */ +#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */ +#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */ +#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */ +#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic + IN NAK. */ +#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic + IN NAK. */ +#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */ +#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */ +#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */ +#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN + NAK status. */ +#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */ +#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */ +/** @} */ + +/** + * @name DSTS register bit definitions + * @{ + */ +#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received + SOF mask. */ +#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received + SOF value. */ +#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received + SOF value. */ +#define DSTS_EERR (1U<<3) /**< Erratic error. */ +#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */ +#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is + running at 48 MHz). */ +#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed. */ +#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */ +/** @} */ + +/** + * @name DIEPMSK register bit definitions + * @{ + */ +#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */ +#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective + mask. */ +#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when + TxFIFO empty mask. */ +#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */ +#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled + interrupt mask. */ +#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed + interrupt mask. */ +/** @} */ + +/** + * @name DOEPMSK register bit definitions + * @{ + */ +#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when + endpoint disabled mask. */ +#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */ +#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled + interrupt mask. */ +#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed + interrupt mask. */ +/** @} */ + +/** + * @name DAINT register bit definitions + * @{ + */ +#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt + bits mask. */ +#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt + bits value. */ +#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt + bits mask. */ +#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt + bits value. */ +/** @} */ + +/** + * @name DAINTMSK register bit definitions + * @{ + */ +#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask + bits mask. */ +#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask + bits value. */ +#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask + bits mask. */ +#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask + bits value. */ +/** @} */ + +/** + * @name DVBUSDIS register bit definitions + * @{ + */ +#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge + time mask. */ +#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge + time value. */ +/** @} */ + +/** + * @name DVBUSPULSE register bit definitions + * @{ + */ +#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time + mask. */ +#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time + value. */ +/** @} */ + +/** + * @name DIEPEMPMSK register bit definitions + * @{ + */ +#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty + interrupt mask bit. */ +/** @} */ + +/** + * @name DIEPCTL register bit definitions + * @{ + */ +#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ +#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ +#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ +#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ +#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ +#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ +#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */ +#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */ +#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */ +#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */ +#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */ +#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */ +#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */ +#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ +#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ +#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ +#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ +#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */ +#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ +#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ +#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ +#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ +#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ +/** @} */ + +/** + * @name DIEPINT register bit definitions + * @{ + */ +#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */ +#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */ +#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when + TxFIFO is empty. */ +#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */ +#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled + interrupt. */ +#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */ +/** @} */ + +/** + * @name DIEPTSIZ register bit definitions + * @{ + */ +#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */ +#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */ +#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */ +#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ +#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ +#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ +/** @} */ + +/** + * @name DTXFSTS register bit definitions. + * @{ + */ +#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space + available. */ +/** @} */ + +/** + * @name DOEPCTL register bit definitions. + * @{ + */ +#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ +#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ +#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ +#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ +#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ +#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ +#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */ +#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */ +#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */ +#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */ +#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ +#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ +#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ +#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ +#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ +#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */ +#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ +#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ +#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ +#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ +#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ +/** @} */ + +/** + * @name DOEPINT register bit definitions + * @{ + */ +#define DOEPINT_SETUP_RCVD (1U<<15) /**< SETUP packet received. */ +#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets + received. */ +#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when + endpoint disabled. */ +#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */ +#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled + interrupt. */ +#define DOEPINT_XFRC (1U<<0) /**< Transfer completed + interrupt. */ +/** @} */ + +/** + * @name DOEPTSIZ register bit definitions + * @{ + */ +#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */ +#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */ +#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */ +#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */ +#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ +#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ +#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ +#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ +/** @} */ + +/** + * @name PCGCCTL register bit definitions + * @{ + */ +#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */ +#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */ +#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */ +/** @} */ + +#if defined(STM32H7XX) || defined(__DOXYGEN__) +/** + * @brief OTG_FS registers block memory address. + */ +#define OTG_FS_ADDR 0x40080000 + +/** + * @brief OTG_HS registers block memory address. + */ +#define OTG_HS_ADDR 0x40040000 +#else +#define OTG_FS_ADDR 0x50000000 +#define OTG_HS_ADDR 0x40040000 +#endif + +/** + * @brief Accesses to the OTG_FS registers block. + */ +#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR) + +/** + * @brief Accesses to the OTG_HS registers block. + */ +#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR) + +#endif /* STM32_OTG_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk b/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk index e59aec084b..eaec8176f0 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1 diff --git a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c index 915135ccf9..7301d80335 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c @@ -1,383 +1,383 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file QUADSPIv1//hal_wspi_lld.c - * @brief STM32 WSPI subsystem low level driver source. - * - * @addtogroup WSPI - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define QUADSPI1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_WSPI_QUADSPI1_DMA_STREAM, \ - STM32_QUADSPI1_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief QUADSPI1 driver identifier.*/ -#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__) -WSPIDriver WSPID1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Waits for completion of previous operation. - */ -static inline void wspi_lld_sync(WSPIDriver *wspip) { - - while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) { - } -} - -/** - * @brief Shared service routine. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void wspi_lld_serve_dma_interrupt(WSPIDriver *wspip, uint32_t flags) { - - (void)wspip; - (void)flags; - - /* DMA errors handling.*/ -#if defined(STM32_WSPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_WSPI_DMA_ERROR_HOOK(wspip); - } -#endif -} - -/** - * @brief Shared service routine. - * - * @param[in] wspip pointer to the @p WSPIDriver object - */ -static void wspi_lld_serve_interrupt(WSPIDriver *wspip) { - - /* Portable WSPI ISR code defined in the high level driver, note, it is - a macro.*/ - _wspi_isr_code(wspip); - - /* Stop everything, we need to give DMA enough time to complete the ongoing - operation. Race condition hidden here.*/ - while (dmaStreamGetTransactionSize(wspip->dma) > 0U) - ; - - /* Clearing DMA interrupts here because the DMA ISR is not called on - transfer complete.*/ - dmaStreamClearInterrupt(wspip->dma); - dmaStreamDisable(wspip->dma); - -#if defined(STM32L471xx) || defined(STM32L475xx) || \ - defined(STM32L476xx) || defined(STM32L486xx) - /* Handling of errata: Extra data written in the FIFO at the end of a - read transfer.*/ - if (wspip->state == WSPI_RECEIVE) { - while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) { - (void) wspip->qspi->DR; - } - } -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__) -#if !defined(STM32_QUADSPI1_SUPPRESS_ISR) -#if !defined(STM32_QUADSPI1_HANDLER) -#error "STM32_QUADSPI1_HANDLER not defined" -#endif -/** - * @brief STM32_QUADSPI1_HANDLER interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_QUADSPI1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - QUADSPI->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | - QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF; - - wspi_lld_serve_interrupt(&WSPID1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_QUADSPI1_SUPPRESS_ISR) */ -#endif /* STM32_WSPI_USE_QUADSPI1 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level WSPI driver initialization. - * - * @notapi - */ -void wspi_lld_init(void) { - -#if STM32_WSPI_USE_QUADSPI1 - wspiObjectInit(&WSPID1); - WSPID1.qspi = QUADSPI; - WSPID1.dma = NULL; - WSPID1.dmamode = STM32_DMA_CR_CHSEL(QUADSPI1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_WSPI_QUADSPI1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_BYTE | - STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - nvicEnableVector(STM32_QUADSPI1_NUMBER, STM32_WSPI_QUADSPI1_IRQ_PRIORITY); -#endif -} - -/** - * @brief Configures and activates the WSPI peripheral. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_start(WSPIDriver *wspip) { - - /* If in stopped state then full initialization.*/ - if (wspip->state == WSPI_STOP) { -#if STM32_WSPI_USE_QUADSPI1 - if (&WSPID1 == wspip) { - wspip->dma = dmaStreamAllocI(STM32_WSPI_QUADSPI1_DMA_STREAM, - STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, - (void *)wspip); - osalDbgAssert(wspip->dma != NULL, "unable to allocate stream"); - rccEnableQUADSPI1(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_QUADSPI); -#endif - } -#endif - - /* Common initializations.*/ - dmaStreamSetPeripheral(wspip->dma, &wspip->qspi->DR); - } - - /* WSPI setup and enable.*/ - wspip->qspi->DCR = wspip->config->dcr; - wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) | - QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN; - wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | - QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF; -} - -/** - * @brief Deactivates the WSPI peripheral. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_stop(WSPIDriver *wspip) { - - /* If in ready state then disables the QUADSPI clock.*/ - if (wspip->state == WSPI_READY) { - - /* WSPI disable.*/ - wspip->qspi->CR = 0U; - - /* Releasing the DMA.*/ - dmaStreamFreeI(wspip->dma); - wspip->dma = NULL; - - /* Stopping involved clocks.*/ -#if STM32_WSPI_USE_QUADSPI1 - if (&WSPID1 == wspip) { - rccDisableQUADSPI1(); - } -#endif - } -} - -/** - * @brief Sends a command without data phase. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * - * @notapi - */ -void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { - -#if STM32_USE_STM32_D1_WORKAROUND == TRUE - /* If it is a command without address and alternate phases then the command - is sent as an alternate byte, the command phase is suppressed.*/ - if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { - /* The command mode field is copied in the alternate mode field. All - other fields are not used in this scenario.*/ - wspip->qspi->DLR = 0U; - wspip->qspi->ABR = cmdp->cmd; - wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U; - return; - } -#endif - wspip->qspi->DLR = 0U; - wspip->qspi->ABR = cmdp->alt; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->qspi->AR = cmdp->addr; - } - - /* Waiting for the previous operation to complete.*/ - wspi_lld_sync(wspip); -} - -/** - * @brief Sends a command with data over the WSPI bus. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[in] n number of bytes to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, const uint8_t *txbuf) { - - dmaStreamSetMemory0(wspip->dma, txbuf); - dmaStreamSetTransactionSize(wspip->dma, n); - dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P); - - wspip->qspi->DLR = n - 1; - wspip->qspi->ABR = cmdp->alt; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->qspi->AR = cmdp->addr; - } - - dmaStreamEnable(wspip->dma); -} - -/** - * @brief Sends a command then receives data over the WSPI bus. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[in] n number of bytes to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, uint8_t *rxbuf) { - - dmaStreamSetMemory0(wspip->dma, rxbuf); - dmaStreamSetTransactionSize(wspip->dma, n); - dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M); - - wspip->qspi->DLR = n - 1; - wspip->qspi->ABR = cmdp->alt; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | - QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | - QUADSPI_CCR_FMODE_0; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->qspi->AR = cmdp->addr; - } - - dmaStreamEnable(wspip->dma); -} - -#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) -/** - * @brief Maps in memory space a WSPI flash device. - * @pre The memory flash device must be initialized appropriately - * before mapping it in memory space. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[out] addrp pointer to the memory start address of the mapped - * flash or @p NULL - * - * @notapi - */ -void wspi_lld_map_flash(WSPIDriver *wspip, - const wspi_command_t *cmdp, - uint8_t **addrp) { - - /* Disabling the DMA request while in memory mapped mode.*/ - wspip->qspi->CR &= ~QUADSPI_CR_DMAEN; - - /* Starting memory mapped mode using the passed parameters.*/ - wspip->qspi->DLR = 0; - wspip->qspi->ABR = 0; - wspip->qspi->AR = 0; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | - QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | - QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0; - - /* Mapped flash absolute base address.*/ - if (addrp != NULL) { - *addrp = (uint8_t *)0x90000000; - } -} - -/** - * @brief Unmaps from memory space a WSPI flash device. - * @post The memory flash device must be re-initialized for normal - * commands exchange. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_unmap_flash(WSPIDriver *wspip) { - - /* Aborting memory mapped mode.*/ - wspip->qspi->CR |= QUADSPI_CR_ABORT; - while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) { - } - - /* Re-enabling DMA request, we are going back to indirect mode.*/ - wspip->qspi->CR |= QUADSPI_CR_DMAEN; -} -#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ - -#endif /* HAL_USE_WSPI */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file QUADSPIv1//hal_wspi_lld.c + * @brief STM32 WSPI subsystem low level driver source. + * + * @addtogroup WSPI + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define QUADSPI1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_WSPI_QUADSPI1_DMA_STREAM, \ + STM32_QUADSPI1_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief QUADSPI1 driver identifier.*/ +#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__) +WSPIDriver WSPID1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Waits for completion of previous operation. + */ +static inline void wspi_lld_sync(WSPIDriver *wspip) { + + while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) { + } +} + +/** + * @brief Shared service routine. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void wspi_lld_serve_dma_interrupt(WSPIDriver *wspip, uint32_t flags) { + + (void)wspip; + (void)flags; + + /* DMA errors handling.*/ +#if defined(STM32_WSPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_WSPI_DMA_ERROR_HOOK(wspip); + } +#endif +} + +/** + * @brief Shared service routine. + * + * @param[in] wspip pointer to the @p WSPIDriver object + */ +static void wspi_lld_serve_interrupt(WSPIDriver *wspip) { + + /* Portable WSPI ISR code defined in the high level driver, note, it is + a macro.*/ + _wspi_isr_code(wspip); + + /* Stop everything, we need to give DMA enough time to complete the ongoing + operation. Race condition hidden here.*/ + while (dmaStreamGetTransactionSize(wspip->dma) > 0U) + ; + + /* Clearing DMA interrupts here because the DMA ISR is not called on + transfer complete.*/ + dmaStreamClearInterrupt(wspip->dma); + dmaStreamDisable(wspip->dma); + +#if defined(STM32L471xx) || defined(STM32L475xx) || \ + defined(STM32L476xx) || defined(STM32L486xx) + /* Handling of errata: Extra data written in the FIFO at the end of a + read transfer.*/ + if (wspip->state == WSPI_RECEIVE) { + while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) { + (void) wspip->qspi->DR; + } + } +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__) +#if !defined(STM32_QUADSPI1_SUPPRESS_ISR) +#if !defined(STM32_QUADSPI1_HANDLER) +#error "STM32_QUADSPI1_HANDLER not defined" +#endif +/** + * @brief STM32_QUADSPI1_HANDLER interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_QUADSPI1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + QUADSPI->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | + QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF; + + wspi_lld_serve_interrupt(&WSPID1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_QUADSPI1_SUPPRESS_ISR) */ +#endif /* STM32_WSPI_USE_QUADSPI1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level WSPI driver initialization. + * + * @notapi + */ +void wspi_lld_init(void) { + +#if STM32_WSPI_USE_QUADSPI1 + wspiObjectInit(&WSPID1); + WSPID1.qspi = QUADSPI; + WSPID1.dma = NULL; + WSPID1.dmamode = STM32_DMA_CR_CHSEL(QUADSPI1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_WSPI_QUADSPI1_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_BYTE | + STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + nvicEnableVector(STM32_QUADSPI1_NUMBER, STM32_WSPI_QUADSPI1_IRQ_PRIORITY); +#endif +} + +/** + * @brief Configures and activates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_start(WSPIDriver *wspip) { + + /* If in stopped state then full initialization.*/ + if (wspip->state == WSPI_STOP) { +#if STM32_WSPI_USE_QUADSPI1 + if (&WSPID1 == wspip) { + wspip->dma = dmaStreamAllocI(STM32_WSPI_QUADSPI1_DMA_STREAM, + STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt, + (void *)wspip); + osalDbgAssert(wspip->dma != NULL, "unable to allocate stream"); + rccEnableQUADSPI1(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_QUADSPI); +#endif + } +#endif + + /* Common initializations.*/ + dmaStreamSetPeripheral(wspip->dma, &wspip->qspi->DR); + } + + /* WSPI setup and enable.*/ + wspip->qspi->DCR = wspip->config->dcr; + wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) | + QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN; + wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | + QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF; +} + +/** + * @brief Deactivates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_stop(WSPIDriver *wspip) { + + /* If in ready state then disables the QUADSPI clock.*/ + if (wspip->state == WSPI_READY) { + + /* WSPI disable.*/ + wspip->qspi->CR = 0U; + + /* Releasing the DMA.*/ + dmaStreamFreeI(wspip->dma); + wspip->dma = NULL; + + /* Stopping involved clocks.*/ +#if STM32_WSPI_USE_QUADSPI1 + if (&WSPID1 == wspip) { + rccDisableQUADSPI1(); + } +#endif + } +} + +/** + * @brief Sends a command without data phase. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * + * @notapi + */ +void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { + +#if STM32_USE_STM32_D1_WORKAROUND == TRUE + /* If it is a command without address and alternate phases then the command + is sent as an alternate byte, the command phase is suppressed.*/ + if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { + /* The command mode field is copied in the alternate mode field. All + other fields are not used in this scenario.*/ + wspip->qspi->DLR = 0U; + wspip->qspi->ABR = cmdp->cmd; + wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U; + return; + } +#endif + wspip->qspi->DLR = 0U; + wspip->qspi->ABR = cmdp->alt; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->qspi->AR = cmdp->addr; + } + + /* Waiting for the previous operation to complete.*/ + wspi_lld_sync(wspip); +} + +/** + * @brief Sends a command with data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf) { + + dmaStreamSetMemory0(wspip->dma, txbuf); + dmaStreamSetTransactionSize(wspip->dma, n); + dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P); + + wspip->qspi->DLR = n - 1; + wspip->qspi->ABR = cmdp->alt; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->qspi->AR = cmdp->addr; + } + + dmaStreamEnable(wspip->dma); +} + +/** + * @brief Sends a command then receives data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf) { + + dmaStreamSetMemory0(wspip->dma, rxbuf); + dmaStreamSetTransactionSize(wspip->dma, n); + dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M); + + wspip->qspi->DLR = n - 1; + wspip->qspi->ABR = cmdp->alt; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | + QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | + QUADSPI_CCR_FMODE_0; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->qspi->AR = cmdp->addr; + } + + dmaStreamEnable(wspip->dma); +} + +#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a WSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @notapi + */ +void wspi_lld_map_flash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp) { + + /* Disabling the DMA request while in memory mapped mode.*/ + wspip->qspi->CR &= ~QUADSPI_CR_DMAEN; + + /* Starting memory mapped mode using the passed parameters.*/ + wspip->qspi->DLR = 0; + wspip->qspi->ABR = 0; + wspip->qspi->AR = 0; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | + QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | + QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0; + + /* Mapped flash absolute base address.*/ + if (addrp != NULL) { + *addrp = (uint8_t *)0x90000000; + } +} + +/** + * @brief Unmaps from memory space a WSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_unmap_flash(WSPIDriver *wspip) { + + /* Aborting memory mapped mode.*/ + wspip->qspi->CR |= QUADSPI_CR_ABORT; + while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) { + } + + /* Re-enabling DMA request, we are going back to indirect mode.*/ + wspip->qspi->CR |= QUADSPI_CR_DMAEN; +} +#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ + +#endif /* HAL_USE_WSPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h index f415dae49e..b7db86c474 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h +++ b/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h @@ -1,313 +1,313 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file QUADSPIv1/hal_wspi_lld.h - * @brief STM32 WSPI subsystem low level driver header. - * - * @addtogroup WSPI - * @{ - */ - -#ifndef HAL_WSPI_LLD_H -#define HAL_WSPI_LLD_H - -#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name WSPI implementation capabilities - * @{ - */ -#define WSPI_SUPPORTS_MEMMAP TRUE -#define WSPI_DEFAULT_CFG_MASKS FALSE -/** @} */ - -/** - * @name Transfer options - * @note The low level driver has the option to override the following - * definitions and use its own ones. In must take care to use - * the same name for the same function or compatibility is not - * ensured. - * @note There are the following limitations in this implementation: - * - Eight lines are not supported. - * - DDR mode is only supported for the whole command, separate - * masks are defined but all define the same bit. - * - Only 8 bits instructions are supported. - * . - * @{ - */ -#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU) -#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU) -#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU) -#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU) -#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU) - -#define WSPI_CFG_CMD_DDR (1LU << 31LU) - -#define WSPI_CFG_CMD_SIZE_MASK 0LU -#define WSPI_CFG_CMD_SIZE_8 0LU - -#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU) -#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU) -#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU) -#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU) -#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU) - -#define WSPI_CFG_ADDR_DDR (1LU << 31LU) - -#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU) - -#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU) -#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU) -#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU) -#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU) -#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU) - -#define WSPI_CFG_ALT_DDR (1LU << 31LU) - -#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU) -#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU) -#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU) -#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU) -#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU) - -#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU) -#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU) -#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU) -#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU) -#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU) - -#define WSPI_CFG_DATA_DDR (1LU << 31LU) - -#define WSPI_CFG_SIOO (1LU << 28LU) -/** @} */ - -/** - * @name Helpers for CCR register. - * @{ - */ -#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU) -#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU) -/** @} */ - -/** - * @name DCR register options - * @{ - */ -#define STM32_DCR_CK_MODE (1U << 0U) -#define STM32_DCR_CSHT_MASK (7U << 8U) -#define STM32_DCR_CSHT(n) ((n) << 8U) -#define STM32_DCR_FSIZE_MASK (31U << 16U) -#define STM32_DCR_FSIZE(n) ((n) << 16U) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief WSPID1 driver enable switch. - * @details If set to @p TRUE the support for QUADSPI1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__) -#define STM32_WSPI_USE_QUADSPI1 FALSE -#endif - -/** - * @brief QUADSPI1 prescaler setting. - * @note This is the prescaler divider value 1..256. The maximum frequency - * varies depending on the STM32 model and operating conditions, - * find the details in the data sheet. - */ -#if !defined(STM32_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__) -#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 -#endif - -/** - * @brief QUADSPI1 interrupt priority level setting. - */ -#if !defined(STM32_WSPI_QUADSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_QUADSPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief QUADSPI1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_WSPI_QUADSPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_QUADSPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief QUADSPI1 DMA interrupt priority level setting. - */ -#if !defined(STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY 10 -#endif - -/** - * @brief QUADSPI DMA error hook. - */ -#if !defined(STM32_WSPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_WSPI_DMA_ERROR_HOOK(wspip) osalSysHalt("DMA failure") -#endif - -/** - * @brief Enables a workaround for a STM32L476 QUADSPI errata. - * @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an - * input when the command is sent in dual or quad SPI mode". - * This workaround makes commands without address or data phases - * to be sent as alternate bytes. - */ -#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__) -#define STM32_USE_STM32_D1_WORKAROUND TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_QUADSPI1) -#define STM32_HAS_QUADSPI1 FALSE -#endif - -#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1 -#error "QUADSPI1 not present in the selected device" -#endif - -#if !STM32_WSPI_USE_QUADSPI1 -#error "WSPI driver activated but no QUADSPI peripheral assigned" -#endif - -#if STM32_WSPI_USE_QUADSPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to QUADSPI1" -#endif - -#if STM32_WSPI_USE_QUADSPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to QUADSPI1 DMA" -#endif - -#if STM32_WSPI_USE_QUADSPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to QUADSPI1" -#endif - -#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \ - (STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256) -#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_DMA_STREAM) -#error "QUADSPI1 DMA stream not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_WSPI_USE_QUADSPI1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_QUADSPI1_DMA_STREAM) -#error "invalid DMA stream associated to QUADSPI1" -#endif - -/* Devices without DMAMUX require an additional check.*/ -#if !STM32_DMA_SUPPORTS_DMAMUX - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_WSPI_USE_QUADSPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_WSPI_QUADSPI1_DMA_STREAM, STM32_QUADSPI1_DMA_MSK) -#error "invalid DMA stream associated to QUADSPI1" -#endif - -#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the WSPI configuration structure. - */ -#define wspi_lld_config_fields \ - /* DCR register initialization data.*/ \ - uint32_t dcr - -/** - * @brief Low level fields of the WSPI driver structure. - */ -#define wspi_lld_driver_fields \ - /* Pointer to the QUADSPIx registers block.*/ \ - QUADSPI_TypeDef *qspi; \ - /* QUADSPI DMA stream.*/ \ - const stm32_dma_stream_t *dma; \ - /* QUADSPI DMA mode bit mask.*/ \ - uint32_t dmamode - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__) -extern WSPIDriver WSPID1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void wspi_lld_init(void); - void wspi_lld_start(WSPIDriver *wspip); - void wspi_lld_stop(WSPIDriver *wspip); - void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp); - void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, const uint8_t *txbuf); - void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, uint8_t *rxbuf); -#if WSPI_SUPPORTS_MEMMAP == TRUE - void wspi_lld_map_flash(WSPIDriver *wspip, - const wspi_command_t *cmdp, - uint8_t **addrp); - void wspi_lld_unmap_flash(WSPIDriver *wspip); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_WSPI */ - -#endif /* HAL_WSPI_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file QUADSPIv1/hal_wspi_lld.h + * @brief STM32 WSPI subsystem low level driver header. + * + * @addtogroup WSPI + * @{ + */ + +#ifndef HAL_WSPI_LLD_H +#define HAL_WSPI_LLD_H + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name WSPI implementation capabilities + * @{ + */ +#define WSPI_SUPPORTS_MEMMAP TRUE +#define WSPI_DEFAULT_CFG_MASKS FALSE +/** @} */ + +/** + * @name Transfer options + * @note The low level driver has the option to override the following + * definitions and use its own ones. In must take care to use + * the same name for the same function or compatibility is not + * ensured. + * @note There are the following limitations in this implementation: + * - Eight lines are not supported. + * - DDR mode is only supported for the whole command, separate + * masks are defined but all define the same bit. + * - Only 8 bits instructions are supported. + * . + * @{ + */ +#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU) +#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU) +#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU) +#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU) +#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU) + +#define WSPI_CFG_CMD_DDR (1LU << 31LU) + +#define WSPI_CFG_CMD_SIZE_MASK 0LU +#define WSPI_CFG_CMD_SIZE_8 0LU + +#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU) +#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU) +#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU) +#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU) +#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU) + +#define WSPI_CFG_ADDR_DDR (1LU << 31LU) + +#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU) + +#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU) +#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU) +#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU) +#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU) +#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU) + +#define WSPI_CFG_ALT_DDR (1LU << 31LU) + +#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU) +#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU) +#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU) +#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU) +#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU) + +#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU) +#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU) +#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU) +#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU) +#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU) + +#define WSPI_CFG_DATA_DDR (1LU << 31LU) + +#define WSPI_CFG_SIOO (1LU << 28LU) +/** @} */ + +/** + * @name Helpers for CCR register. + * @{ + */ +#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU) +#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU) +/** @} */ + +/** + * @name DCR register options + * @{ + */ +#define STM32_DCR_CK_MODE (1U << 0U) +#define STM32_DCR_CSHT_MASK (7U << 8U) +#define STM32_DCR_CSHT(n) ((n) << 8U) +#define STM32_DCR_FSIZE_MASK (31U << 16U) +#define STM32_DCR_FSIZE(n) ((n) << 16U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief WSPID1 driver enable switch. + * @details If set to @p TRUE the support for QUADSPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__) +#define STM32_WSPI_USE_QUADSPI1 FALSE +#endif + +/** + * @brief QUADSPI1 prescaler setting. + * @note This is the prescaler divider value 1..256. The maximum frequency + * varies depending on the STM32 model and operating conditions, + * find the details in the data sheet. + */ +#if !defined(STM32_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 +#endif + +/** + * @brief QUADSPI1 interrupt priority level setting. + */ +#if !defined(STM32_WSPI_QUADSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_QUADSPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief QUADSPI1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_WSPI_QUADSPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_QUADSPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief QUADSPI1 DMA interrupt priority level setting. + */ +#if !defined(STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY 10 +#endif + +/** + * @brief QUADSPI DMA error hook. + */ +#if !defined(STM32_WSPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_WSPI_DMA_ERROR_HOOK(wspip) osalSysHalt("DMA failure") +#endif + +/** + * @brief Enables a workaround for a STM32L476 QUADSPI errata. + * @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an + * input when the command is sent in dual or quad SPI mode". + * This workaround makes commands without address or data phases + * to be sent as alternate bytes. + */ +#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__) +#define STM32_USE_STM32_D1_WORKAROUND TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_QUADSPI1) +#define STM32_HAS_QUADSPI1 FALSE +#endif + +#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1 +#error "QUADSPI1 not present in the selected device" +#endif + +#if !STM32_WSPI_USE_QUADSPI1 +#error "WSPI driver activated but no QUADSPI peripheral assigned" +#endif + +#if STM32_WSPI_USE_QUADSPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to QUADSPI1" +#endif + +#if STM32_WSPI_USE_QUADSPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to QUADSPI1 DMA" +#endif + +#if STM32_WSPI_USE_QUADSPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to QUADSPI1" +#endif + +#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \ + (STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256) +#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_DMA_STREAM) +#error "QUADSPI1 DMA stream not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_WSPI_USE_QUADSPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_QUADSPI1_DMA_STREAM) +#error "invalid DMA stream associated to QUADSPI1" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if !STM32_DMA_SUPPORTS_DMAMUX + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_WSPI_USE_QUADSPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_WSPI_QUADSPI1_DMA_STREAM, STM32_QUADSPI1_DMA_MSK) +#error "invalid DMA stream associated to QUADSPI1" +#endif + +#endif /* !STM32_DMA_SUPPORTS_DMAMUX */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the WSPI configuration structure. + */ +#define wspi_lld_config_fields \ + /* DCR register initialization data.*/ \ + uint32_t dcr + +/** + * @brief Low level fields of the WSPI driver structure. + */ +#define wspi_lld_driver_fields \ + /* Pointer to the QUADSPIx registers block.*/ \ + QUADSPI_TypeDef *qspi; \ + /* QUADSPI DMA stream.*/ \ + const stm32_dma_stream_t *dma; \ + /* QUADSPI DMA mode bit mask.*/ \ + uint32_t dmamode + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__) +extern WSPIDriver WSPID1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void wspi_lld_init(void); + void wspi_lld_start(WSPIDriver *wspip); + void wspi_lld_stop(WSPIDriver *wspip); + void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp); + void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf); + void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf); +#if WSPI_SUPPORTS_MEMMAP == TRUE + void wspi_lld_map_flash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp); + void wspi_lld_unmap_flash(WSPIDriver *wspip); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_WSPI */ + +#endif /* HAL_WSPI_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk b/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk index 0a9e0992c5..91ea2d3eb2 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk +++ b/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2 diff --git a/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c b/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c index 7f9cb1aea0..a7e9a330bd 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c +++ b/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c @@ -1,382 +1,382 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file QUADSPIv2/hal_wspi_lld.c - * @brief STM32 WSPI subsystem low level driver source. - * - * @addtogroup WSPI - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* @brief MDMA HW request is QSPI FIFO threshold Flag */ -#define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U) - -/* @brief MDMA HW request is QSPI Transfer complete Flag */ -#define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief QUADSPI1 driver identifier.*/ -#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__) -WSPIDriver WSPID1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Waits for completion of previous operation. - */ -static inline void wspi_lld_sync(WSPIDriver *wspip) { - - while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) { - } -} - -/** - * @brief Shared service routine. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] flags content of the CISR register - */ -static void wspi_lld_serve_mdma_interrupt(WSPIDriver *wspip, uint32_t flags) { - - (void)wspip; - (void)flags; - - if (((flags & STM32_MDMA_CISR_CTCIF) != 0U) && - (wspip->state == WSPI_RECEIVE)) { - /* Portable WSPI ISR code defined in the high level driver, note, it is - a macro.*/ - _wspi_isr_code(wspip); - - mdmaChannelDisableX(wspip->mdma); - } - /* DMA errors handling.*/ -#if defined(STM32_WSPI_MDMA_ERROR_HOOK) - else if ((flags & STM32_MDMA_CISR_TEIF) != 0) { - STM32_WSPI_MDMA_ERROR_HOOK(wspip); - } -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level WSPI driver initialization. - * - * @notapi - */ -void wspi_lld_init(void) { - -#if STM32_WSPI_USE_QUADSPI1 - wspiObjectInit(&WSPID1); - WSPID1.qspi = QUADSPI; - WSPID1.mdma = NULL; -#endif -} - -/** - * @brief Configures and activates the WSPI peripheral. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_start(WSPIDriver *wspip) { - - /* If in stopped state then full initialization.*/ - if (wspip->state == WSPI_STOP) { -#if STM32_WSPI_USE_QUADSPI1 - if (&WSPID1 == wspip) { - wspip->mdma = mdmaChannelAllocI(STM32_WSPI_QUADSPI1_MDMA_CHANNEL, - (stm32_mdmaisr_t)wspi_lld_serve_mdma_interrupt, - (void *)wspip); - osalDbgAssert(wspip->mdma != NULL, "unable to allocate MDMA channel"); - rccEnableQUADSPI1(true); - } -#endif - } - - /* WSPI setup and enable.*/ - wspip->qspi->DCR = wspip->config->dcr; -#if STM32_WSPI_SET_CR_SSHIFT - wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) | - QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_SSHIFT | - QUADSPI_CR_EN; -#else - wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) | - QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN; -#endif - wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | - QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF; -} - -/** - * @brief Deactivates the WSPI peripheral. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_stop(WSPIDriver *wspip) { - - /* If in ready state then disables the QUADSPI clock.*/ - if (wspip->state == WSPI_READY) { - - /* WSPI disable.*/ - wspip->qspi->CR = 0U; - - /* Releasing the DMA.*/ - mdmaChannelFreeI(wspip->mdma); - wspip->mdma = NULL; - - /* Stopping involved clocks.*/ -#if STM32_WSPI_USE_QUADSPI1 - if (&WSPID1 == wspip) { - rccDisableQUADSPI1(); - } -#endif - } -} - -/** - * @brief Sends a command without data phase. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * - * @notapi - */ -void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { - -#if STM32_USE_STM32_D1_WORKAROUND == TRUE - /* If it is a command without address and alternate phases then the command - is sent as an alternate byte, the command phase is suppressed.*/ - if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { - /* The command mode field is copied in the alternate mode field. All - other fields are not used in this scenario.*/ - wspip->qspi->DLR = 0U; - wspip->qspi->ABR = cmdp->cmd; - wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U; - return; - } -#endif - wspip->qspi->DLR = 0U; - wspip->qspi->ABR = cmdp->alt; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->qspi->AR = cmdp->addr; - } - - /* Waiting for the previous operation to complete.*/ - wspi_lld_sync(wspip); -} - -/** - * @brief Sends a command with data over the WSPI bus. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[in] n number of bytes to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, const uint8_t *txbuf) { - uint32_t ctcr = STM32_MDMA_CTCR_BWM_NON_BUFF | /* Dest. non-cacheable. */ - STM32_MDMA_CTCR_TRGM_BUFFER | /* Trigger on buffer. */ - STM32_MDMA_CTCR_TLEN(0U) | /* One byte buffer. */ - STM32_MDMA_CTCR_DBURST_1 | /* Assuming AXI bus. */ - STM32_MDMA_CTCR_SBURST_1 | /* Assuming AXI bus. */ - STM32_MDMA_CTCR_DINCOS_BYTE | /* Byte increment. */ - STM32_MDMA_CTCR_SINCOS_BYTE | /* Byte increment. */ - STM32_MDMA_CTCR_DSIZE_BYTE | /* Destination size. */ - STM32_MDMA_CTCR_SSIZE_BYTE | /* Source size. */ - STM32_MDMA_CTCR_DINC_FIXED | /* Destination fixed. */ - STM32_MDMA_CTCR_SINC_INC; /* Source incremented. */ - uint32_t ccr = STM32_MDMA_CCR_PL(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) | - STM32_MDMA_CCR_TEIE; /* On transfer error. */ - - /* MDMA initializations.*/ - mdmaChannelSetSourceX(wspip->mdma, txbuf); - mdmaChannelSetDestinationX(wspip->mdma, &wspip->qspi->DR); - mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0); - mdmaChannelSetModeX(wspip->mdma, ctcr, ccr); - mdmaChannelSetTrigModeX(wspip->mdma, MDMA_REQUEST_QUADSPI_FIFO_TH); - - wspip->qspi->DLR = n - 1; - wspip->qspi->ABR = cmdp->alt; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->qspi->AR = cmdp->addr; - } - - mdmaChannelEnableX(wspip->mdma); -} - -/** - * @brief Sends a command then receives data over the WSPI bus. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[in] n number of bytes to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, uint8_t *rxbuf) { - uint32_t ctcr = STM32_MDMA_CTCR_BWM_NON_BUFF | /* Dest. non-cacheable. */ - STM32_MDMA_CTCR_TRGM_BUFFER | /* Trigger on buffer. */ - STM32_MDMA_CTCR_TLEN(0) | /* One byte buffer. */ - STM32_MDMA_CTCR_DBURST_1 | /* Assuming AXI bus. */ - STM32_MDMA_CTCR_SBURST_1 | /* Assuming AXI bus. */ - STM32_MDMA_CTCR_DINCOS_BYTE | /* Byte increment. */ - STM32_MDMA_CTCR_SINCOS_BYTE | /* Byte increment. */ - STM32_MDMA_CTCR_DSIZE_BYTE | /* Destination size. */ - STM32_MDMA_CTCR_SSIZE_BYTE | /* Source size. */ - STM32_MDMA_CTCR_DINC_INC | /* Destination incr. */ - STM32_MDMA_CTCR_SINC_FIXED; /* Source fixed. */ - uint32_t ccr = STM32_MDMA_CCR_PL(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) | - STM32_MDMA_CCR_CTCIE | /* On transfer complete.*/ - STM32_MDMA_CCR_TEIE; /* On transfer error. */ - - /* MDMA initializations.*/ - mdmaChannelSetSourceX(wspip->mdma, &wspip->qspi->DR); - mdmaChannelSetDestinationX(wspip->mdma, rxbuf); - mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0); - mdmaChannelSetModeX(wspip->mdma, ctcr, ccr); - mdmaChannelSetTrigModeX(wspip->mdma, MDMA_REQUEST_QUADSPI_FIFO_TH); - - wspip->qspi->DLR = n - 1; - wspip->qspi->ABR = cmdp->alt; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | - QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | - QUADSPI_CCR_FMODE_0; - if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { - wspip->qspi->AR = cmdp->addr; - } - - mdmaChannelEnableX(wspip->mdma); -} - -#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) -/** - * @brief Maps in memory space a WSPI flash device. - * @pre The memory flash device must be initialized appropriately - * before mapping it in memory space. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * @param[in] cmdp pointer to the command descriptor - * @param[out] addrp pointer to the memory start address of the mapped - * flash or @p NULL - * - * @notapi - */ -void wspi_lld_map_flash(WSPIDriver *wspip, - const wspi_command_t *cmdp, - uint8_t **addrp) { - - /* Disabling the DMA request while in memory mapped mode.*/ - wspip->qspi->CR &= ~QUADSPI_CR_DMAEN; - - /* Starting memory mapped mode using the passed parameters.*/ - wspip->qspi->DLR = 0; - wspip->qspi->ABR = 0; - wspip->qspi->AR = 0; - wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | - QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | - QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0; - - /* Mapped flash absolute base address.*/ - if (addrp != NULL) { - *addrp = (uint8_t *)0x90000000; - } -} - -/** - * @brief Unmaps from memory space a WSPI flash device. - * @post The memory flash device must be re-initialized for normal - * commands exchange. - * - * @param[in] wspip pointer to the @p WSPIDriver object - * - * @notapi - */ -void wspi_lld_unmap_flash(WSPIDriver *wspip) { - - /* Aborting memory mapped mode.*/ - wspip->qspi->CR |= QUADSPI_CR_ABORT; - while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) { - } - - /* Re-enabling DMA request, we are going back to indirect mode.*/ - wspip->qspi->CR |= QUADSPI_CR_DMAEN; -} -#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ - -/** - * @brief Shared service routine. - * - * @param[in] wspip pointer to the @p WSPIDriver object - */ -void wspi_lld_serve_interrupt(WSPIDriver *wspip) { - uint32_t sr; - - sr = wspip->qspi->SR; - wspip->qspi->FCR = sr; - - if (((sr & QUADSPI_FCR_CTCF) != 0U) && (wspip->state == WSPI_SEND)) { - /* Portable WSPI ISR code defined in the high level driver, note, it is - a macro.*/ - _wspi_isr_code(wspip); - - mdmaChannelDisableX(wspip->mdma); - } - - /* TODO errors handling.*/ -} - -#endif /* HAL_USE_WSPI */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file QUADSPIv2/hal_wspi_lld.c + * @brief STM32 WSPI subsystem low level driver source. + * + * @addtogroup WSPI + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* @brief MDMA HW request is QSPI FIFO threshold Flag */ +#define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U) + +/* @brief MDMA HW request is QSPI Transfer complete Flag */ +#define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief QUADSPI1 driver identifier.*/ +#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__) +WSPIDriver WSPID1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Waits for completion of previous operation. + */ +static inline void wspi_lld_sync(WSPIDriver *wspip) { + + while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) { + } +} + +/** + * @brief Shared service routine. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] flags content of the CISR register + */ +static void wspi_lld_serve_mdma_interrupt(WSPIDriver *wspip, uint32_t flags) { + + (void)wspip; + (void)flags; + + if (((flags & STM32_MDMA_CISR_CTCIF) != 0U) && + (wspip->state == WSPI_RECEIVE)) { + /* Portable WSPI ISR code defined in the high level driver, note, it is + a macro.*/ + _wspi_isr_code(wspip); + + mdmaChannelDisableX(wspip->mdma); + } + /* DMA errors handling.*/ +#if defined(STM32_WSPI_MDMA_ERROR_HOOK) + else if ((flags & STM32_MDMA_CISR_TEIF) != 0) { + STM32_WSPI_MDMA_ERROR_HOOK(wspip); + } +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level WSPI driver initialization. + * + * @notapi + */ +void wspi_lld_init(void) { + +#if STM32_WSPI_USE_QUADSPI1 + wspiObjectInit(&WSPID1); + WSPID1.qspi = QUADSPI; + WSPID1.mdma = NULL; +#endif +} + +/** + * @brief Configures and activates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_start(WSPIDriver *wspip) { + + /* If in stopped state then full initialization.*/ + if (wspip->state == WSPI_STOP) { +#if STM32_WSPI_USE_QUADSPI1 + if (&WSPID1 == wspip) { + wspip->mdma = mdmaChannelAllocI(STM32_WSPI_QUADSPI1_MDMA_CHANNEL, + (stm32_mdmaisr_t)wspi_lld_serve_mdma_interrupt, + (void *)wspip); + osalDbgAssert(wspip->mdma != NULL, "unable to allocate MDMA channel"); + rccEnableQUADSPI1(true); + } +#endif + } + + /* WSPI setup and enable.*/ + wspip->qspi->DCR = wspip->config->dcr; +#if STM32_WSPI_SET_CR_SSHIFT + wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) | + QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_SSHIFT | + QUADSPI_CR_EN; +#else + wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) | + QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN; +#endif + wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | + QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF; +} + +/** + * @brief Deactivates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_stop(WSPIDriver *wspip) { + + /* If in ready state then disables the QUADSPI clock.*/ + if (wspip->state == WSPI_READY) { + + /* WSPI disable.*/ + wspip->qspi->CR = 0U; + + /* Releasing the DMA.*/ + mdmaChannelFreeI(wspip->mdma); + wspip->mdma = NULL; + + /* Stopping involved clocks.*/ +#if STM32_WSPI_USE_QUADSPI1 + if (&WSPID1 == wspip) { + rccDisableQUADSPI1(); + } +#endif + } +} + +/** + * @brief Sends a command without data phase. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * + * @notapi + */ +void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) { + +#if STM32_USE_STM32_D1_WORKAROUND == TRUE + /* If it is a command without address and alternate phases then the command + is sent as an alternate byte, the command phase is suppressed.*/ + if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) { + /* The command mode field is copied in the alternate mode field. All + other fields are not used in this scenario.*/ + wspip->qspi->DLR = 0U; + wspip->qspi->ABR = cmdp->cmd; + wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U; + return; + } +#endif + wspip->qspi->DLR = 0U; + wspip->qspi->ABR = cmdp->alt; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->qspi->AR = cmdp->addr; + } + + /* Waiting for the previous operation to complete.*/ + wspi_lld_sync(wspip); +} + +/** + * @brief Sends a command with data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf) { + uint32_t ctcr = STM32_MDMA_CTCR_BWM_NON_BUFF | /* Dest. non-cacheable. */ + STM32_MDMA_CTCR_TRGM_BUFFER | /* Trigger on buffer. */ + STM32_MDMA_CTCR_TLEN(0U) | /* One byte buffer. */ + STM32_MDMA_CTCR_DBURST_1 | /* Assuming AXI bus. */ + STM32_MDMA_CTCR_SBURST_1 | /* Assuming AXI bus. */ + STM32_MDMA_CTCR_DINCOS_BYTE | /* Byte increment. */ + STM32_MDMA_CTCR_SINCOS_BYTE | /* Byte increment. */ + STM32_MDMA_CTCR_DSIZE_BYTE | /* Destination size. */ + STM32_MDMA_CTCR_SSIZE_BYTE | /* Source size. */ + STM32_MDMA_CTCR_DINC_FIXED | /* Destination fixed. */ + STM32_MDMA_CTCR_SINC_INC; /* Source incremented. */ + uint32_t ccr = STM32_MDMA_CCR_PL(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) | + STM32_MDMA_CCR_TEIE; /* On transfer error. */ + + /* MDMA initializations.*/ + mdmaChannelSetSourceX(wspip->mdma, txbuf); + mdmaChannelSetDestinationX(wspip->mdma, &wspip->qspi->DR); + mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0); + mdmaChannelSetModeX(wspip->mdma, ctcr, ccr); + mdmaChannelSetTrigModeX(wspip->mdma, MDMA_REQUEST_QUADSPI_FIFO_TH); + + wspip->qspi->DLR = n - 1; + wspip->qspi->ABR = cmdp->alt; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->qspi->AR = cmdp->addr; + } + + mdmaChannelEnableX(wspip->mdma); +} + +/** + * @brief Sends a command then receives data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf) { + uint32_t ctcr = STM32_MDMA_CTCR_BWM_NON_BUFF | /* Dest. non-cacheable. */ + STM32_MDMA_CTCR_TRGM_BUFFER | /* Trigger on buffer. */ + STM32_MDMA_CTCR_TLEN(0) | /* One byte buffer. */ + STM32_MDMA_CTCR_DBURST_1 | /* Assuming AXI bus. */ + STM32_MDMA_CTCR_SBURST_1 | /* Assuming AXI bus. */ + STM32_MDMA_CTCR_DINCOS_BYTE | /* Byte increment. */ + STM32_MDMA_CTCR_SINCOS_BYTE | /* Byte increment. */ + STM32_MDMA_CTCR_DSIZE_BYTE | /* Destination size. */ + STM32_MDMA_CTCR_SSIZE_BYTE | /* Source size. */ + STM32_MDMA_CTCR_DINC_INC | /* Destination incr. */ + STM32_MDMA_CTCR_SINC_FIXED; /* Source fixed. */ + uint32_t ccr = STM32_MDMA_CCR_PL(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) | + STM32_MDMA_CCR_CTCIE | /* On transfer complete.*/ + STM32_MDMA_CCR_TEIE; /* On transfer error. */ + + /* MDMA initializations.*/ + mdmaChannelSetSourceX(wspip->mdma, &wspip->qspi->DR); + mdmaChannelSetDestinationX(wspip->mdma, rxbuf); + mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0); + mdmaChannelSetModeX(wspip->mdma, ctcr, ccr); + mdmaChannelSetTrigModeX(wspip->mdma, MDMA_REQUEST_QUADSPI_FIFO_TH); + + wspip->qspi->DLR = n - 1; + wspip->qspi->ABR = cmdp->alt; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | + QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | + QUADSPI_CCR_FMODE_0; + if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) { + wspip->qspi->AR = cmdp->addr; + } + + mdmaChannelEnableX(wspip->mdma); +} + +#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a WSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @notapi + */ +void wspi_lld_map_flash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp) { + + /* Disabling the DMA request while in memory mapped mode.*/ + wspip->qspi->CR &= ~QUADSPI_CR_DMAEN; + + /* Starting memory mapped mode using the passed parameters.*/ + wspip->qspi->DLR = 0; + wspip->qspi->ABR = 0; + wspip->qspi->AR = 0; + wspip->qspi->CCR = cmdp->cmd | cmdp->cfg | + QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) | + QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0; + + /* Mapped flash absolute base address.*/ + if (addrp != NULL) { + *addrp = (uint8_t *)0x90000000; + } +} + +/** + * @brief Unmaps from memory space a WSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +void wspi_lld_unmap_flash(WSPIDriver *wspip) { + + /* Aborting memory mapped mode.*/ + wspip->qspi->CR |= QUADSPI_CR_ABORT; + while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) { + } + + /* Re-enabling DMA request, we are going back to indirect mode.*/ + wspip->qspi->CR |= QUADSPI_CR_DMAEN; +} +#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ + +/** + * @brief Shared service routine. + * + * @param[in] wspip pointer to the @p WSPIDriver object + */ +void wspi_lld_serve_interrupt(WSPIDriver *wspip) { + uint32_t sr; + + sr = wspip->qspi->SR; + wspip->qspi->FCR = sr; + + if (((sr & QUADSPI_FCR_CTCF) != 0U) && (wspip->state == WSPI_SEND)) { + /* Portable WSPI ISR code defined in the high level driver, note, it is + a macro.*/ + _wspi_isr_code(wspip); + + mdmaChannelDisableX(wspip->mdma); + } + + /* TODO errors handling.*/ +} + +#endif /* HAL_USE_WSPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h b/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h index 2452bb255f..229c3220f0 100644 --- a/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h +++ b/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h @@ -1,286 +1,286 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file QUADSPIv2/hal_wspi_lld.h - * @brief STM32 WSPI subsystem low level driver header. - * - * @addtogroup WSPI - * @{ - */ - -#ifndef HAL_WSPI_LLD_H -#define HAL_WSPI_LLD_H - -#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name WSPI implementation capabilities - * @{ - */ -#define WSPI_SUPPORTS_MEMMAP TRUE -#define WSPI_DEFAULT_CFG_MASKS FALSE -/** @} */ - -/** - * @name Transfer options - * @note The low level driver has the option to override the following - * definitions and use its own ones. In must take care to use - * the same name for the same function or compatibility is not - * ensured. - * @note There are the following limitations in this implementation: - * - Eight lines are not supported. - * - DDR mode is only supported for the whole command, separate - * masks are defined but all define the same bit. - * - Only 8 bits instructions are supported. - * . - * @{ - */ -#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU) -#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU) -#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU) -#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU) -#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU) - -#define WSPI_CFG_CMD_DDR (1LU << 31LU) - -#define WSPI_CFG_CMD_SIZE_MASK 0LU -#define WSPI_CFG_CMD_SIZE_8 0LU - -#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU) -#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU) -#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU) -#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU) -#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU) - -#define WSPI_CFG_ADDR_DDR (1LU << 31LU) - -#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU) -#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU) - -#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU) -#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU) -#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU) -#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU) -#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU) - -#define WSPI_CFG_ALT_DDR (1LU << 31LU) - -#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU) -#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU) -#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU) -#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU) -#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU) - -#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU) -#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU) -#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU) -#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU) -#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU) - -#define WSPI_CFG_DATA_DDR (1LU << 31LU) - -#define WSPI_CFG_SIOO (1LU << 28LU) -/** @} */ - -/** - * @name Helpers for CCR register. - * @{ - */ -#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU) -#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU) -/** @} */ - -/** - * @name DCR register options - * @{ - */ -#define STM32_DCR_CK_MODE (1U << 0U) -#define STM32_DCR_CSHT_MASK (7U << 8U) -#define STM32_DCR_CSHT(n) ((n) << 8U) -#define STM32_DCR_FSIZE_MASK (31U << 16U) -#define STM32_DCR_FSIZE(n) ((n) << 16U) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief WSPID1 driver enable switch. - * @details If set to @p TRUE the support for QUADSPI1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__) -#define STM32_WSPI_USE_QUADSPI1 FALSE -#endif - -/** - * @brief QUADSPI1 prescaler setting. - * @note This is the prescaler divider value 1..256. The maximum frequency - * varies depending on the STM32 model and operating conditions, - * find the details in the data sheet. - */ -#if !defined(STM32_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__) -#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 -#endif - -/** - * @brief QUADSPI1 CR_SSHIFT enforcing. - */ -#if !defined(STM32_WSPI_SET_CR_SSHIFT) || defined(__DOXYGEN__) -#define STM32_WSPI_SET_CR_SSHIFT TRUE -#endif - -/** - * @brief QUADSPI1 MDMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_WSPI_QUADSPI1_MDMA_PRIORITY 1 -#endif - -/** - * @brief QUADSPI MDMA error hook. - */ -#if !defined(STM32_WSPI_MDMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_WSPI_MDMA_ERROR_HOOK(wspip) osalSysHalt("MDMA failure") -#endif - -/** - * @brief Enables a workaround for a STM32L476 QUADSPI errata. - * @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an - * input when the command is sent in dual or quad SPI mode". - * This workaround makes commands without address or data phases - * to be sent as alternate bytes. - */ -#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__) -#define STM32_USE_STM32_D1_WORKAROUND TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_QUADSPI1) -#define STM32_HAS_QUADSPI1 FALSE -#endif - -#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1 -#error "QUADSPI1 not present in the selected device" -#endif - -#if !STM32_WSPI_USE_QUADSPI1 -#error "WSPI driver activated but no QUADSPI peripheral assigned" -#endif - -/* MDMA-related checks.*/ -#if STM32_WSPI_USE_QUADSPI1 && \ - !STM32_MDMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) -#error "Invalid MDMA priority assigned to QUADSPI1" -#endif - -/* Checks on prescaler setting.*/ -#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \ - (STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256) -#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256" -#endif - -/* Check on the presence of the DMA channels settings in mcuconf.h.*/ -#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_MDMA_CHANNEL) -#error "QUADSPI1 MDMA channel not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_WSPI_USE_QUADSPI1 && \ - !STM32_MDMA_IS_VALID_CHANNEL(STM32_WSPI_QUADSPI1_MDMA_CHANNEL) -#error "invalid MDMA channel associated to QUADSPI1" -#endif - -#if !defined(STM32_MDMA_REQUIRED) -#define STM32_MDMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the WSPI configuration structure. - */ -#define wspi_lld_config_fields \ - /* DCR register initialization data.*/ \ - uint32_t dcr - -/** - * @brief Low level fields of the WSPI driver structure. - */ -#define wspi_lld_driver_fields \ - /* Pointer to the QUADSPIx registers block.*/ \ - QUADSPI_TypeDef *qspi; \ - /* QUADSPI MDMA channel.*/ \ - const stm32_mdma_channel_t *mdma - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__) -extern WSPIDriver WSPID1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void wspi_lld_init(void); - void wspi_lld_start(WSPIDriver *wspip); - void wspi_lld_stop(WSPIDriver *wspip); - void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp); - void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, const uint8_t *txbuf); - void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, - size_t n, uint8_t *rxbuf); -#if WSPI_SUPPORTS_MEMMAP == TRUE - void wspi_lld_map_flash(WSPIDriver *wspip, - const wspi_command_t *cmdp, - uint8_t **addrp); - void wspi_lld_unmap_flash(WSPIDriver *wspip); -#endif - void wspi_lld_serve_interrupt(WSPIDriver *wspip); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_WSPI */ - -#endif /* HAL_WSPI_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file QUADSPIv2/hal_wspi_lld.h + * @brief STM32 WSPI subsystem low level driver header. + * + * @addtogroup WSPI + * @{ + */ + +#ifndef HAL_WSPI_LLD_H +#define HAL_WSPI_LLD_H + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name WSPI implementation capabilities + * @{ + */ +#define WSPI_SUPPORTS_MEMMAP TRUE +#define WSPI_DEFAULT_CFG_MASKS FALSE +/** @} */ + +/** + * @name Transfer options + * @note The low level driver has the option to override the following + * definitions and use its own ones. In must take care to use + * the same name for the same function or compatibility is not + * ensured. + * @note There are the following limitations in this implementation: + * - Eight lines are not supported. + * - DDR mode is only supported for the whole command, separate + * masks are defined but all define the same bit. + * - Only 8 bits instructions are supported. + * . + * @{ + */ +#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU) +#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU) +#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU) +#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU) +#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU) + +#define WSPI_CFG_CMD_DDR (1LU << 31LU) + +#define WSPI_CFG_CMD_SIZE_MASK 0LU +#define WSPI_CFG_CMD_SIZE_8 0LU + +#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU) +#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU) +#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU) +#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU) +#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU) + +#define WSPI_CFG_ADDR_DDR (1LU << 31LU) + +#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU) + +#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU) +#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU) +#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU) +#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU) +#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU) + +#define WSPI_CFG_ALT_DDR (1LU << 31LU) + +#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU) +#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU) +#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU) +#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU) +#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU) + +#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU) +#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU) +#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU) +#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU) +#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU) + +#define WSPI_CFG_DATA_DDR (1LU << 31LU) + +#define WSPI_CFG_SIOO (1LU << 28LU) +/** @} */ + +/** + * @name Helpers for CCR register. + * @{ + */ +#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU) +#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU) +/** @} */ + +/** + * @name DCR register options + * @{ + */ +#define STM32_DCR_CK_MODE (1U << 0U) +#define STM32_DCR_CSHT_MASK (7U << 8U) +#define STM32_DCR_CSHT(n) ((n) << 8U) +#define STM32_DCR_FSIZE_MASK (31U << 16U) +#define STM32_DCR_FSIZE(n) ((n) << 16U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief WSPID1 driver enable switch. + * @details If set to @p TRUE the support for QUADSPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__) +#define STM32_WSPI_USE_QUADSPI1 FALSE +#endif + +/** + * @brief QUADSPI1 prescaler setting. + * @note This is the prescaler divider value 1..256. The maximum frequency + * varies depending on the STM32 model and operating conditions, + * find the details in the data sheet. + */ +#if !defined(STM32_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__) +#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 +#endif + +/** + * @brief QUADSPI1 CR_SSHIFT enforcing. + */ +#if !defined(STM32_WSPI_SET_CR_SSHIFT) || defined(__DOXYGEN__) +#define STM32_WSPI_SET_CR_SSHIFT TRUE +#endif + +/** + * @brief QUADSPI1 MDMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_WSPI_QUADSPI1_MDMA_PRIORITY 1 +#endif + +/** + * @brief QUADSPI MDMA error hook. + */ +#if !defined(STM32_WSPI_MDMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_WSPI_MDMA_ERROR_HOOK(wspip) osalSysHalt("MDMA failure") +#endif + +/** + * @brief Enables a workaround for a STM32L476 QUADSPI errata. + * @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an + * input when the command is sent in dual or quad SPI mode". + * This workaround makes commands without address or data phases + * to be sent as alternate bytes. + */ +#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__) +#define STM32_USE_STM32_D1_WORKAROUND TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_QUADSPI1) +#define STM32_HAS_QUADSPI1 FALSE +#endif + +#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1 +#error "QUADSPI1 not present in the selected device" +#endif + +#if !STM32_WSPI_USE_QUADSPI1 +#error "WSPI driver activated but no QUADSPI peripheral assigned" +#endif + +/* MDMA-related checks.*/ +#if STM32_WSPI_USE_QUADSPI1 && \ + !STM32_MDMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) +#error "Invalid MDMA priority assigned to QUADSPI1" +#endif + +/* Checks on prescaler setting.*/ +#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \ + (STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256) +#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256" +#endif + +/* Check on the presence of the DMA channels settings in mcuconf.h.*/ +#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_MDMA_CHANNEL) +#error "QUADSPI1 MDMA channel not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_WSPI_USE_QUADSPI1 && \ + !STM32_MDMA_IS_VALID_CHANNEL(STM32_WSPI_QUADSPI1_MDMA_CHANNEL) +#error "invalid MDMA channel associated to QUADSPI1" +#endif + +#if !defined(STM32_MDMA_REQUIRED) +#define STM32_MDMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the WSPI configuration structure. + */ +#define wspi_lld_config_fields \ + /* DCR register initialization data.*/ \ + uint32_t dcr + +/** + * @brief Low level fields of the WSPI driver structure. + */ +#define wspi_lld_driver_fields \ + /* Pointer to the QUADSPIx registers block.*/ \ + QUADSPI_TypeDef *qspi; \ + /* QUADSPI MDMA channel.*/ \ + const stm32_mdma_channel_t *mdma + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__) +extern WSPIDriver WSPID1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void wspi_lld_init(void); + void wspi_lld_start(WSPIDriver *wspip); + void wspi_lld_stop(WSPIDriver *wspip); + void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp); + void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf); + void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf); +#if WSPI_SUPPORTS_MEMMAP == TRUE + void wspi_lld_map_flash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp); + void wspi_lld_unmap_flash(WSPIDriver *wspip); +#endif + void wspi_lld_serve_interrupt(WSPIDriver *wspip); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_WSPI */ + +#endif /* HAL_WSPI_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RNGv1/driver.mk b/os/hal/ports/STM32/LLD/RNGv1/driver.mk index 3c905004a4..35ba327814 100644 --- a/os/hal/ports/STM32/LLD/RNGv1/driver.mk +++ b/os/hal/ports/STM32/LLD/RNGv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_TRNG TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_TRNG TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1 diff --git a/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c b/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c index c81e433f6c..3708c1cac8 100644 --- a/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c +++ b/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c @@ -1,179 +1,179 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_trng_lld.c - * @brief STM32 TRNG subsystem low level driver source. - * - * @addtogroup TRNG - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief TRNGD1 driver identifier. - */ -#if (STM32_TRNG_USE_RNG1 == TRUE) || defined(__DOXYGEN__) -TRNGDriver TRNGD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const TRNGConfig default_cfg = {.cr = 0}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level TRNG driver initialization. - * - * @notapi - */ -void trng_lld_init(void) { - -#if STM32_TRNG_USE_RNG1 == TRUE - /* Driver initialization.*/ - trngObjectInit(&TRNGD1); - TRNGD1.rng = RNG; -#endif -} - -/** - * @brief Configures and activates the TRNG peripheral. - * - * @param[in] trngp pointer to the @p TRNGDriver object - * - * @notapi - */ -void trng_lld_start(TRNGDriver *trngp) { - - /* There is no real configuration but setting up a valid pointer anyway.*/ - if (trngp->config == NULL) { - trngp->config = &default_cfg; - } - - if (trngp->state == TRNG_STOP) { - /* Enables the peripheral.*/ -#if STM32_TRNG_USE_RNG1 == TRUE - if (&TRNGD1 == trngp) { - rccEnableRNG(false); - } -#endif - } - /* Configures the peripheral.*/ - trngp->rng->CR |= RNG_CR_RNGEN; -} - -/** - * @brief Deactivates the TRNG peripheral. - * - * @param[in] trngp pointer to the @p TRNGDriver object - * - * @notapi - */ -void trng_lld_stop(TRNGDriver *trngp) { - - if (trngp->state == TRNG_READY) { - /* Resets the peripheral.*/ - trngp->rng->CR &= ~RNG_CR_RNGEN; - - /* Disables the peripheral.*/ -#if STM32_TRNG_USE_RNG1 == TRUE - if (&TRNGD1 == trngp) { - rccDisableRNG(); - } -#endif - } -} - -/** - * @brief True random numbers generator. - * @note The function is blocking and likely performs polled waiting - * inside the low level implementation. - * - * @param[in] trngp pointer to the @p TRNGDriver object - * @param[in] size size of output buffer - * @param[out] out output buffer - * @return The operation status. - * @retval false if a random number has been generated. - * @retval true if an HW error occurred. - * - * @api - */ -bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out) { - - while (true) { - uint32_t r, tmo; - size_t i; - - /* Waiting for error conditions to be cleared.*/ - tmo = STM32_TRNG_ERROR_CLEAR_ATTEMPTS; - while ((tmo > 0) && ((trngp->rng->SR & (RNG_SR_CECS | RNG_SR_SECS)) != 0)) { - tmo--; - if (tmo == 0) { - return true; - } - } - - /* Waiting for a random number in data register.*/ - tmo = STM32_DATA_FETCH_ATTEMPTS; - while ((tmo > 0) && ((trngp->rng->SR & RNG_SR_DRDY) == 0)) { - tmo--; - if (tmo == 0) { - return true; - } - } - - /* Getting the generated random number.*/ - r = trngp->rng->DR; - - /* Writing in the output buffer.*/ - for (i = 0; i < sizeof (uint32_t) / sizeof (uint8_t); i++) { - *out++ = (uint8_t)r; - r = r >> 8; - size--; - if (size == 0) { - return false; - } - } - } -} - -#endif /* HAL_USE_TRNG == TRUE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_trng_lld.c + * @brief STM32 TRNG subsystem low level driver source. + * + * @addtogroup TRNG + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief TRNGD1 driver identifier. + */ +#if (STM32_TRNG_USE_RNG1 == TRUE) || defined(__DOXYGEN__) +TRNGDriver TRNGD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const TRNGConfig default_cfg = {.cr = 0}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level TRNG driver initialization. + * + * @notapi + */ +void trng_lld_init(void) { + +#if STM32_TRNG_USE_RNG1 == TRUE + /* Driver initialization.*/ + trngObjectInit(&TRNGD1); + TRNGD1.rng = RNG; +#endif +} + +/** + * @brief Configures and activates the TRNG peripheral. + * + * @param[in] trngp pointer to the @p TRNGDriver object + * + * @notapi + */ +void trng_lld_start(TRNGDriver *trngp) { + + /* There is no real configuration but setting up a valid pointer anyway.*/ + if (trngp->config == NULL) { + trngp->config = &default_cfg; + } + + if (trngp->state == TRNG_STOP) { + /* Enables the peripheral.*/ +#if STM32_TRNG_USE_RNG1 == TRUE + if (&TRNGD1 == trngp) { + rccEnableRNG(false); + } +#endif + } + /* Configures the peripheral.*/ + trngp->rng->CR |= RNG_CR_RNGEN; +} + +/** + * @brief Deactivates the TRNG peripheral. + * + * @param[in] trngp pointer to the @p TRNGDriver object + * + * @notapi + */ +void trng_lld_stop(TRNGDriver *trngp) { + + if (trngp->state == TRNG_READY) { + /* Resets the peripheral.*/ + trngp->rng->CR &= ~RNG_CR_RNGEN; + + /* Disables the peripheral.*/ +#if STM32_TRNG_USE_RNG1 == TRUE + if (&TRNGD1 == trngp) { + rccDisableRNG(); + } +#endif + } +} + +/** + * @brief True random numbers generator. + * @note The function is blocking and likely performs polled waiting + * inside the low level implementation. + * + * @param[in] trngp pointer to the @p TRNGDriver object + * @param[in] size size of output buffer + * @param[out] out output buffer + * @return The operation status. + * @retval false if a random number has been generated. + * @retval true if an HW error occurred. + * + * @api + */ +bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out) { + + while (true) { + uint32_t r, tmo; + size_t i; + + /* Waiting for error conditions to be cleared.*/ + tmo = STM32_TRNG_ERROR_CLEAR_ATTEMPTS; + while ((tmo > 0) && ((trngp->rng->SR & (RNG_SR_CECS | RNG_SR_SECS)) != 0)) { + tmo--; + if (tmo == 0) { + return true; + } + } + + /* Waiting for a random number in data register.*/ + tmo = STM32_DATA_FETCH_ATTEMPTS; + while ((tmo > 0) && ((trngp->rng->SR & RNG_SR_DRDY) == 0)) { + tmo--; + if (tmo == 0) { + return true; + } + } + + /* Getting the generated random number.*/ + r = trngp->rng->DR; + + /* Writing in the output buffer.*/ + for (i = 0; i < sizeof (uint32_t) / sizeof (uint8_t); i++) { + *out++ = (uint8_t)r; + r = r >> 8; + size--; + if (size == 0) { + return false; + } + } + } +} + +#endif /* HAL_USE_TRNG == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h b/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h index 2a1e9ba469..b39392b596 100644 --- a/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h +++ b/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h @@ -1,141 +1,141 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_trng_lld.h - * @brief STM32 TRNG subsystem low level driver header. - * - * @addtogroup TRNG - * @{ - */ - -#ifndef HAL_TRNG_LLD_H -#define HAL_TRNG_LLD_H - -#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name STM32 configuration options - * @{ - */ -/** - * @brief TRNGD1 driver enable switch. - * @details If set to @p TRUE the support for TRNGD1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_TRNG_USE_RNG1) || defined(__DOXYGEN__) -#define STM32_TRNG_USE_RNG1 FALSE -#endif - -/** - * @brief TRNGD1 error clear timeout counter. - * @details Number of status register fetches before failing. - */ -#if !defined(STM32_TRNG_ERROR_CLEAR_ATTEMPTS) || defined(__DOXYGEN__) -#define STM32_TRNG_ERROR_CLEAR_ATTEMPTS 1000 -#endif - -/** - * @brief TRNGD1 data available timeout counter. - * @details Number of status register fetches before failing. - */ -#if !defined(STM32_DATA_FETCH_ATTEMPTS) || defined(__DOXYGEN__) -#define STM32_DATA_FETCH_ATTEMPTS 1000 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_RNG1) -#define STM32_HAS_RNG1 FALSE -#endif - -#if STM32_TRNG_USE_RNG1 && !STM32_HAS_RNG1 -#error "RNG1 not present in the selected device" -#endif - -#if !STM32_TRNG_USE_RNG1 -#error "TRNG driver activated but no RNG peripheral assigned" -#endif - -#if !defined(STM32_RNGCLK) -#error "STM32_RNGCLK not defined in this HAL" -#endif - -#if ((STM32_RNGCLK < 47000000) || (STM32_RNGCLK > 49000000)) && \ - ((STM32_RNGCLK < 3500000) || (STM32_RNGCLK > 4500000)) -#if !defined(STM32_DISABLE_RNG_CLOCK_CHECK) -#error "STM32_RNGCLK is not within a tested clock range" -#error "define STM32_DISABLE_RNG_CLOCK_CHECK to override this check" -#endif -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the TRNG configuration structure. - */ -#define trng_lld_config_fields \ - /* CR register initialization value.*/ \ - uint32_t cr - -/** - * @brief Low level fields of the TRNG driver structure. - */ -#define trng_lld_driver_fields \ - /* Pointer to the RNG registers block.*/ \ - RNG_TypeDef *rng - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if (STM32_TRNG_USE_RNG1 == TRUE) && !defined(__DOXYGEN__) -extern TRNGDriver TRNGD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void trng_lld_init(void); - void trng_lld_start(TRNGDriver *trngp); - void trng_lld_stop(TRNGDriver *trngp); - bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_TRNG == TRUE */ - -#endif /* HAL_TRNG_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_trng_lld.h + * @brief STM32 TRNG subsystem low level driver header. + * + * @addtogroup TRNG + * @{ + */ + +#ifndef HAL_TRNG_LLD_H +#define HAL_TRNG_LLD_H + +#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name STM32 configuration options + * @{ + */ +/** + * @brief TRNGD1 driver enable switch. + * @details If set to @p TRUE the support for TRNGD1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_TRNG_USE_RNG1) || defined(__DOXYGEN__) +#define STM32_TRNG_USE_RNG1 FALSE +#endif + +/** + * @brief TRNGD1 error clear timeout counter. + * @details Number of status register fetches before failing. + */ +#if !defined(STM32_TRNG_ERROR_CLEAR_ATTEMPTS) || defined(__DOXYGEN__) +#define STM32_TRNG_ERROR_CLEAR_ATTEMPTS 1000 +#endif + +/** + * @brief TRNGD1 data available timeout counter. + * @details Number of status register fetches before failing. + */ +#if !defined(STM32_DATA_FETCH_ATTEMPTS) || defined(__DOXYGEN__) +#define STM32_DATA_FETCH_ATTEMPTS 1000 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_RNG1) +#define STM32_HAS_RNG1 FALSE +#endif + +#if STM32_TRNG_USE_RNG1 && !STM32_HAS_RNG1 +#error "RNG1 not present in the selected device" +#endif + +#if !STM32_TRNG_USE_RNG1 +#error "TRNG driver activated but no RNG peripheral assigned" +#endif + +#if !defined(STM32_RNGCLK) +#error "STM32_RNGCLK not defined in this HAL" +#endif + +#if ((STM32_RNGCLK < 47000000) || (STM32_RNGCLK > 49000000)) && \ + ((STM32_RNGCLK < 3500000) || (STM32_RNGCLK > 4500000)) +#if !defined(STM32_DISABLE_RNG_CLOCK_CHECK) +#error "STM32_RNGCLK is not within a tested clock range" +#error "define STM32_DISABLE_RNG_CLOCK_CHECK to override this check" +#endif +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the TRNG configuration structure. + */ +#define trng_lld_config_fields \ + /* CR register initialization value.*/ \ + uint32_t cr + +/** + * @brief Low level fields of the TRNG driver structure. + */ +#define trng_lld_driver_fields \ + /* Pointer to the RNG registers block.*/ \ + RNG_TypeDef *rng + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (STM32_TRNG_USE_RNG1 == TRUE) && !defined(__DOXYGEN__) +extern TRNGDriver TRNGD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void trng_lld_init(void); + void trng_lld_start(TRNGDriver *trngp); + void trng_lld_stop(TRNGDriver *trngp); + bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_TRNG == TRUE */ + +#endif /* HAL_TRNG_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RNGv1/notes.txt b/os/hal/ports/STM32/LLD/RNGv1/notes.txt index 8e0c8e530d..5216b28c9f 100644 --- a/os/hal/ports/STM32/LLD/RNGv1/notes.txt +++ b/os/hal/ports/STM32/LLD/RNGv1/notes.txt @@ -1,10 +1,10 @@ -STM32 RNGv1 driver. - -Driver capability: - -- Supports the STM32 TRNGv1 found on STM32L4 and STM32L4+ families. - -The file registry must export: - -STM32_HAS_RNG1 - RNG presence flag. - +STM32 RNGv1 driver. + +Driver capability: + +- Supports the STM32 TRNGv1 found on STM32L4 and STM32L4+ families. + +The file registry must export: + +STM32_HAS_RNG1 - RNG presence flag. + diff --git a/os/hal/ports/STM32/LLD/RTCv1/driver.mk b/os/hal/ports/STM32/LLD/RTCv1/driver.mk index 972b475b50..1dbb3b7733 100644 --- a/os/hal/ports/STM32/LLD/RTCv1/driver.mk +++ b/os/hal/ports/STM32/LLD/RTCv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1 diff --git a/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c b/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c index 248a9c3cc1..40d523dbc3 100644 --- a/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c +++ b/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c @@ -1,447 +1,447 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file RTCv1/hal_rtc_lld.c - * @brief STM32 RTC subsystem low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief RTC driver identifier. - */ -RTCDriver RTCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Wait for synchronization of RTC registers with APB1 bus. - * @details This function must be invoked before trying to read RTC registers - * in the backup domain: DIV, CNT, ALR. CR registers can always - * be read. - * - * @notapi - */ -static void rtc_apb1_sync(void) { - - while ((RTC->CRL & RTC_CRL_RSF) == 0) - ; -} - -/** - * @brief Wait for for previous write operation complete. - * @details This function must be invoked before writing to any RTC registers - * - * @notapi - */ -static void rtc_wait_write_completed(void) { - - while ((RTC->CRL & RTC_CRL_RTOFF) == 0) - ; -} - -/** - * @brief Acquires write access to RTC registers. - * @details Before writing to the backup domain RTC registers the previous - * write operation must be completed. Use this function before - * writing to PRL, CNT, ALR registers. - * - * @notapi - */ -static void rtc_acquire_access(void) { - - rtc_wait_write_completed(); - RTC->CRL |= RTC_CRL_CNF; -} - -/** - * @brief Releases write access to RTC registers. - * - * @notapi - */ -static void rtc_release_access(void) { - - RTC->CRL &= ~RTC_CRL_CNF; -} - -/** - * @brief Converts time from timespec to seconds counter. - * - * @param[in] timespec pointer to a @p RTCDateTime structure - * @return the TR register encoding. - * - * @notapi - */ -static time_t rtc_encode(const RTCDateTime *timespec) { - struct tm tim; - - rtcConvertDateTimeToStructTm(timespec, &tim, NULL); - return mktime(&tim); -} - -/** - * @brief Converts time from seconds/milliseconds to timespec. - * - * @param[in] tv_sec seconds value - * @param[in] tv_msec milliseconds value - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -static void rtc_decode(uint32_t tv_sec, - uint32_t tv_msec, - RTCDateTime *timespec) { - struct tm tim; - struct tm *t; - const time_t time = (const time_t)tv_sec; /* Could be 64 bits.*/ - - /* If the conversion is successful the function returns a pointer - to the object the result was written into.*/ -#if defined(__GNUC__) || defined(__CC_ARM) - t = localtime_r(&time, &tim); - osalDbgAssert(t != NULL, "conversion failed"); -#else - t = localtime(&time); - memcpy(&tim, t, sizeof(struct tm)); -#endif - - rtcConvertStructTmToDateTime(&tim, tv_msec, timespec); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief RTC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC1_HANDLER) { - uint16_t flags; - - OSAL_IRQ_PROLOGUE(); - - /* Code hits this wait only when AHB1 bus was previously powered off by any - reason (standby, reset, etc). In other cases there is no waiting.*/ - rtc_apb1_sync(); - - /* Mask of all enabled and pending sources.*/ - flags = RTCD1.rtc->CRH & RTCD1.rtc->CRL; - RTCD1.rtc->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF); - - if (flags & RTC_CRL_SECF) - RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); - - if (flags & RTC_CRL_ALRF) - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM); - - if (flags & RTC_CRL_OWF) - RTCD1.callback(&RTCD1, RTC_EVENT_OVERFLOW); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Load value of RTCCLK to prescaler registers. - * @note The pre-scaler must not be set on every reset as RTC clock - * counts are lost when it is set. - * @note This function designed to be called from - * hal_lld_backup_domain_init(). Because there is only place - * where possible to detect BKP domain reset event reliably. - * - * @notapi - */ -void rtc_lld_set_prescaler(void) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - rtc_acquire_access(); - RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F; - RTC->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF); - rtc_release_access(); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Initialize RTC. - * - * @notapi - */ -void rtc_lld_init(void) { - - /* RTC object initialization.*/ - rtcObjectInit(&RTCD1); - - /* RTC pointer initialization.*/ - RTCD1.rtc = RTC; - - /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock - stop. Otherwise its value will not be actual. */ - RTCD1.rtc->CRL &= ~RTC_CRL_RSF; - - /* Required because access to PRL.*/ - rtc_apb1_sync(); - - /* All interrupts initially disabled.*/ - rtc_wait_write_completed(); - RTCD1.rtc->CRH = 0; - - /* Callback initially disabled.*/ - RTCD1.callback = NULL; - - /* IRQ vector permanently assigned to this driver.*/ - nvicEnableVector(STM32_RTC1_NUMBER, STM32_RTC_IRQ_PRIORITY); -} - -/** - * @brief Set current time. - * @note Fractional part will be silently ignored. There is no possibility - * to change it on STM32F1xx platform. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { - time_t tv_sec = rtc_encode(timespec); - - rtcSTM32SetSec(rtcp, tv_sec); -} - -/** - * @brief Get current time. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { - uint32_t tv_sec, tv_msec; - - rtcSTM32GetSecMsec(rtcp, &tv_sec, &tv_msec); - rtc_decode(tv_sec, tv_msec, timespec); -} - -/** - * @brief Set alarm time. - * - * @note Default value after BKP domain reset is 0xFFFFFFFF - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[in] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ -void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm_number, - const RTCAlarm *alarmspec) { - syssts_t sts; - (void)alarm_number; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - rtc_acquire_access(); - if (alarmspec != NULL) { - rtcp->rtc->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); - rtcp->rtc->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); - } - else { - rtcp->rtc->ALRH = 0; - rtcp->rtc->ALRL = 0; - } - rtc_release_access(); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Get current alarm. - * @note If an alarm has not been set then the returned alarm specification - * is not meaningful. - * @note The function can be called from any context. - * @note Default value after BKP domain reset is 0xFFFFFFFF. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ -void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm_number, - RTCAlarm *alarmspec) { - syssts_t sts; - (void)alarm_number; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - /* Required because access to ALR.*/ - rtc_apb1_sync(); - - alarmspec->tv_sec = ((rtcp->rtc->ALRH << 16) + rtcp->rtc->ALRL); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Enables or disables RTC callbacks. - * @details This function enables or disables callbacks, use a @p NULL pointer - * in order to disable a callback. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL - * - * @notapi - */ -void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - if (callback != NULL) { - - /* IRQ sources enabled only after setting up the callback.*/ - rtcp->callback = callback; - - rtc_wait_write_completed(); - rtcp->rtc->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); - rtcp->rtc->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; - } - else { - rtc_wait_write_completed(); - rtcp->rtc->CRH = 0; - - /* Callback set to NULL only after disabling the IRQ sources.*/ - rtcp->callback = NULL; - } - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Get seconds and (optionally) milliseconds from RTC. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] tv_sec pointer to seconds value - * @param[out] tv_msec pointer to milliseconds value, set it - * to @p NULL if not needed - * - * @api - */ -void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec) { - uint32_t time_frac; - syssts_t sts; - - osalDbgCheck((NULL != tv_sec) && (NULL != rtcp)); - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - /* Required because access to CNT and DIV.*/ - rtc_apb1_sync(); - - /* wait for previous write accesses to complete.*/ - rtc_wait_write_completed(); - - /* Loops until two consecutive read returning the same value.*/ - do { - *tv_sec = ((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL; - time_frac = (((uint32_t)rtcp->rtc->DIVH) << 16) + (uint32_t)rtcp->rtc->DIVL; - } while ((*tv_sec) != (((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL)); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); - - if (NULL != tv_msec) - *tv_msec = (((uint32_t)STM32_RTCCLK - 1 - time_frac) * 1000) / STM32_RTCCLK; -} - -/** - * @brief Set seconds in RTC. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] tv_sec seconds value - * - * @api - */ -void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec) { - syssts_t sts; - - osalDbgCheck(NULL != rtcp); - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - rtc_acquire_access(); - rtcp->rtc->CNTH = (uint16_t)(tv_sec >> 16); - rtcp->rtc->CNTL = (uint16_t)(tv_sec & 0xFFFF); - rtc_release_access(); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -#endif /* HAL_USE_RTC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv1/hal_rtc_lld.c + * @brief STM32 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Wait for synchronization of RTC registers with APB1 bus. + * @details This function must be invoked before trying to read RTC registers + * in the backup domain: DIV, CNT, ALR. CR registers can always + * be read. + * + * @notapi + */ +static void rtc_apb1_sync(void) { + + while ((RTC->CRL & RTC_CRL_RSF) == 0) + ; +} + +/** + * @brief Wait for for previous write operation complete. + * @details This function must be invoked before writing to any RTC registers + * + * @notapi + */ +static void rtc_wait_write_completed(void) { + + while ((RTC->CRL & RTC_CRL_RTOFF) == 0) + ; +} + +/** + * @brief Acquires write access to RTC registers. + * @details Before writing to the backup domain RTC registers the previous + * write operation must be completed. Use this function before + * writing to PRL, CNT, ALR registers. + * + * @notapi + */ +static void rtc_acquire_access(void) { + + rtc_wait_write_completed(); + RTC->CRL |= RTC_CRL_CNF; +} + +/** + * @brief Releases write access to RTC registers. + * + * @notapi + */ +static void rtc_release_access(void) { + + RTC->CRL &= ~RTC_CRL_CNF; +} + +/** + * @brief Converts time from timespec to seconds counter. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @return the TR register encoding. + * + * @notapi + */ +static time_t rtc_encode(const RTCDateTime *timespec) { + struct tm tim; + + rtcConvertDateTimeToStructTm(timespec, &tim, NULL); + return mktime(&tim); +} + +/** + * @brief Converts time from seconds/milliseconds to timespec. + * + * @param[in] tv_sec seconds value + * @param[in] tv_msec milliseconds value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +static void rtc_decode(uint32_t tv_sec, + uint32_t tv_msec, + RTCDateTime *timespec) { + struct tm tim; + struct tm *t; + const time_t time = (const time_t)tv_sec; /* Could be 64 bits.*/ + + /* If the conversion is successful the function returns a pointer + to the object the result was written into.*/ +#if defined(__GNUC__) || defined(__CC_ARM) + t = localtime_r(&time, &tim); + osalDbgAssert(t != NULL, "conversion failed"); +#else + t = localtime(&time); + memcpy(&tim, t, sizeof(struct tm)); +#endif + + rtcConvertStructTmToDateTime(&tim, tv_msec, timespec); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief RTC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC1_HANDLER) { + uint16_t flags; + + OSAL_IRQ_PROLOGUE(); + + /* Code hits this wait only when AHB1 bus was previously powered off by any + reason (standby, reset, etc). In other cases there is no waiting.*/ + rtc_apb1_sync(); + + /* Mask of all enabled and pending sources.*/ + flags = RTCD1.rtc->CRH & RTCD1.rtc->CRL; + RTCD1.rtc->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF); + + if (flags & RTC_CRL_SECF) + RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); + + if (flags & RTC_CRL_ALRF) + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM); + + if (flags & RTC_CRL_OWF) + RTCD1.callback(&RTCD1, RTC_EVENT_OVERFLOW); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Load value of RTCCLK to prescaler registers. + * @note The pre-scaler must not be set on every reset as RTC clock + * counts are lost when it is set. + * @note This function designed to be called from + * hal_lld_backup_domain_init(). Because there is only place + * where possible to detect BKP domain reset event reliably. + * + * @notapi + */ +void rtc_lld_set_prescaler(void) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + rtc_acquire_access(); + RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F; + RTC->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF); + rtc_release_access(); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Initialize RTC. + * + * @notapi + */ +void rtc_lld_init(void) { + + /* RTC object initialization.*/ + rtcObjectInit(&RTCD1); + + /* RTC pointer initialization.*/ + RTCD1.rtc = RTC; + + /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock + stop. Otherwise its value will not be actual. */ + RTCD1.rtc->CRL &= ~RTC_CRL_RSF; + + /* Required because access to PRL.*/ + rtc_apb1_sync(); + + /* All interrupts initially disabled.*/ + rtc_wait_write_completed(); + RTCD1.rtc->CRH = 0; + + /* Callback initially disabled.*/ + RTCD1.callback = NULL; + + /* IRQ vector permanently assigned to this driver.*/ + nvicEnableVector(STM32_RTC1_NUMBER, STM32_RTC_IRQ_PRIORITY); +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to change it on STM32F1xx platform. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { + time_t tv_sec = rtc_encode(timespec); + + rtcSTM32SetSec(rtcp, tv_sec); +} + +/** + * @brief Get current time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { + uint32_t tv_sec, tv_msec; + + rtcSTM32GetSecMsec(rtcp, &tv_sec, &tv_msec); + rtc_decode(tv_sec, tv_msec, timespec); +} + +/** + * @brief Set alarm time. + * + * @note Default value after BKP domain reset is 0xFFFFFFFF + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[in] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm_number, + const RTCAlarm *alarmspec) { + syssts_t sts; + (void)alarm_number; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + rtc_acquire_access(); + if (alarmspec != NULL) { + rtcp->rtc->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); + rtcp->rtc->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); + } + else { + rtcp->rtc->ALRH = 0; + rtcp->rtc->ALRL = 0; + } + rtc_release_access(); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Get current alarm. + * @note If an alarm has not been set then the returned alarm specification + * is not meaningful. + * @note The function can be called from any context. + * @note Default value after BKP domain reset is 0xFFFFFFFF. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm_number, + RTCAlarm *alarmspec) { + syssts_t sts; + (void)alarm_number; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + /* Required because access to ALR.*/ + rtc_apb1_sync(); + + alarmspec->tv_sec = ((rtcp->rtc->ALRH << 16) + rtcp->rtc->ALRL); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Enables or disables RTC callbacks. + * @details This function enables or disables callbacks, use a @p NULL pointer + * in order to disable a callback. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] callback callback function pointer or @p NULL + * + * @notapi + */ +void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + if (callback != NULL) { + + /* IRQ sources enabled only after setting up the callback.*/ + rtcp->callback = callback; + + rtc_wait_write_completed(); + rtcp->rtc->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); + rtcp->rtc->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; + } + else { + rtc_wait_write_completed(); + rtcp->rtc->CRH = 0; + + /* Callback set to NULL only after disabling the IRQ sources.*/ + rtcp->callback = NULL; + } + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Get seconds and (optionally) milliseconds from RTC. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] tv_sec pointer to seconds value + * @param[out] tv_msec pointer to milliseconds value, set it + * to @p NULL if not needed + * + * @api + */ +void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec) { + uint32_t time_frac; + syssts_t sts; + + osalDbgCheck((NULL != tv_sec) && (NULL != rtcp)); + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + /* Required because access to CNT and DIV.*/ + rtc_apb1_sync(); + + /* wait for previous write accesses to complete.*/ + rtc_wait_write_completed(); + + /* Loops until two consecutive read returning the same value.*/ + do { + *tv_sec = ((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL; + time_frac = (((uint32_t)rtcp->rtc->DIVH) << 16) + (uint32_t)rtcp->rtc->DIVL; + } while ((*tv_sec) != (((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL)); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); + + if (NULL != tv_msec) + *tv_msec = (((uint32_t)STM32_RTCCLK - 1 - time_frac) * 1000) / STM32_RTCCLK; +} + +/** + * @brief Set seconds in RTC. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] tv_sec seconds value + * + * @api + */ +void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec) { + syssts_t sts; + + osalDbgCheck(NULL != rtcp); + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + rtc_acquire_access(); + rtcp->rtc->CNTH = (uint16_t)(tv_sec >> 16); + rtcp->rtc->CNTL = (uint16_t)(tv_sec & 0xFFFF); + rtc_release_access(); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +#endif /* HAL_USE_RTC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h b/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h index 09263156d0..7e8b35dd58 100644 --- a/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h +++ b/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h @@ -1,152 +1,152 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file RTCv1/hal_rtc_lld.h - * @brief STM32 RTC subsystem low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#ifndef HAL_RTC_LLD_H -#define HAL_RTC_LLD_H - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Implementation capabilities - */ -/** - * @brief This RTC implementation supports callbacks. - */ -#define RTC_SUPPORTS_CALLBACKS TRUE - -/** - * @brief One alarm comparator available. - */ -#define RTC_ALARMS 1 - -/** - * @brief Presence of a local persistent storage. - */ -#define RTC_HAS_STORAGE FALSE -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/* - * RTC driver system settings. - */ -#define STM32_RTC_IRQ_PRIORITY 15 -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if HAL_USE_RTC && !STM32_HAS_RTC -#error "RTC not present in the selected device" -#endif - -#if STM32_RTCCLK == 0 -#error "RTC clock not enabled" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an RTC event. - */ -typedef enum { - RTC_EVENT_SECOND = 0, /** Triggered every second. */ - RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ - RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ -} rtcevent_t; - -/** - * @brief Type of a generic RTC callback. - */ -typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); - -/** - * @brief Type of a structure representing an RTC alarm time stamp. - */ -typedef struct hal_rtc_alarm { - /** - * @brief Seconds since UNIX epoch. - */ - uint32_t tv_sec; -} RTCAlarm; - -/** - * @brief Implementation-specific @p RTCDriver fields. - */ -#define rtc_lld_driver_fields \ - /* Pointer to the RTC registers block.*/ \ - RTC_TypeDef *rtc; \ - /* Callback pointer.*/ \ - rtccb_t callback - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void rtc_lld_set_prescaler(void); - void rtc_lld_init(void); - void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); - void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); - void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm_number, - const RTCAlarm *alarmspec); - void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm_number, - RTCAlarm *alarmspec); - void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); - void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec); - void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_RTC */ - -#endif /* HAL_RTC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv1/hal_rtc_lld.h + * @brief STM32 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef HAL_RTC_LLD_H +#define HAL_RTC_LLD_H + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Implementation capabilities + */ +/** + * @brief This RTC implementation supports callbacks. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief One alarm comparator available. + */ +#define RTC_ALARMS 1 + +/** + * @brief Presence of a local persistent storage. + */ +#define RTC_HAS_STORAGE FALSE +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/* + * RTC driver system settings. + */ +#define STM32_RTC_IRQ_PRIORITY 15 +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !STM32_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if STM32_RTCCLK == 0 +#error "RTC clock not enabled" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_SECOND = 0, /** Triggered every second. */ + RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ + RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ +} rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct hal_rtc_alarm { + /** + * @brief Seconds since UNIX epoch. + */ + uint32_t tv_sec; +} RTCAlarm; + +/** + * @brief Implementation-specific @p RTCDriver fields. + */ +#define rtc_lld_driver_fields \ + /* Pointer to the RTC registers block.*/ \ + RTC_TypeDef *rtc; \ + /* Callback pointer.*/ \ + rtccb_t callback + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_set_prescaler(void); + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm_number, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm_number, + RTCAlarm *alarmspec); + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); + void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec); + void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* HAL_RTC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RTCv2/driver.mk b/os/hal/ports/STM32/LLD/RTCv2/driver.mk index 25ef11d41e..720f4d331e 100644 --- a/os/hal/ports/STM32/LLD/RTCv2/driver.mk +++ b/os/hal/ports/STM32/LLD/RTCv2/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2 diff --git a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c index 79807ecb97..12c5d32f42 100644 --- a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c +++ b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c @@ -1,854 +1,854 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file RTCv2/hal_rtc_lld.c - * @brief STM32 RTC low level driver. - * - * @addtogroup RTC - * @{ - */ - -#include "hal.h" - -// If you enable subseconds, there is a chance that this code will hang while locked (!) -// See https://github.com/rusefi/rusefi/issues/4557 -#undef STM32_RTC_HAS_SUBSECONDS -#define STM32_RTC_HAS_SUBSECONDS FALSE - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define RTC_TR_PM_OFFSET 22 -#define RTC_TR_HT_OFFSET 20 -#define RTC_TR_HU_OFFSET 16 -#define RTC_TR_MNT_OFFSET 12 -#define RTC_TR_MNU_OFFSET 8 -#define RTC_TR_ST_OFFSET 4 -#define RTC_TR_SU_OFFSET 0 - -#define RTC_DR_YT_OFFSET 20 -#define RTC_DR_YU_OFFSET 16 -#define RTC_DR_WDU_OFFSET 13 -#define RTC_DR_MT_OFFSET 12 -#define RTC_DR_MU_OFFSET 8 -#define RTC_DR_DT_OFFSET 4 -#define RTC_DR_DU_OFFSET 0 - -#define RTC_CR_BKP_OFFSET 18 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief RTC driver identifier. - */ -RTCDriver RTCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Beginning of configuration procedure. - * - * @notapi - */ -static void rtc_enter_init(void) { - - RTCD1.rtc->ISR |= RTC_ISR_INIT; - while ((RTCD1.rtc->ISR & RTC_ISR_INITF) == 0) - ; -} - -/** - * @brief Finalizing of configuration procedure. - * - * @notapi - */ -static inline void rtc_exit_init(void) { - - RTCD1.rtc->ISR &= ~RTC_ISR_INIT; -} - -/** - * @brief Converts time from TR register encoding to timespec. - * - * @param[in] tr TR register value - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -static void rtc_decode_time(uint32_t tr, RTCDateTime *timespec) { - uint32_t n; - - n = ((tr >> RTC_TR_HT_OFFSET) & 3) * 36000000; - n += ((tr >> RTC_TR_HU_OFFSET) & 15) * 3600000; - n += ((tr >> RTC_TR_MNT_OFFSET) & 7) * 600000; - n += ((tr >> RTC_TR_MNU_OFFSET) & 15) * 60000; - n += ((tr >> RTC_TR_ST_OFFSET) & 7) * 10000; - n += ((tr >> RTC_TR_SU_OFFSET) & 15) * 1000; - timespec->millisecond = n; -} - -/** - * @brief Converts date from DR register encoding to timespec. - * - * @param[in] dr DR register value - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -static void rtc_decode_date(uint32_t dr, RTCDateTime *timespec) { - - timespec->year = (((dr >> RTC_DR_YT_OFFSET) & 15) * 10) + - ((dr >> RTC_DR_YU_OFFSET) & 15); - timespec->month = (((dr >> RTC_TR_MNT_OFFSET) & 1) * 10) + - ((dr >> RTC_TR_MNU_OFFSET) & 15); - timespec->day = (((dr >> RTC_DR_DT_OFFSET) & 3) * 10) + - ((dr >> RTC_DR_DU_OFFSET) & 15); - timespec->dayofweek = (dr >> RTC_DR_WDU_OFFSET) & 7; -} - -/** - * @brief Converts time from timespec to TR register encoding. - * - * @param[in] timespec pointer to a @p RTCDateTime structure - * @return the TR register encoding. - * - * @notapi - */ -static uint32_t rtc_encode_time(const RTCDateTime *timespec) { - uint32_t n, tr = 0; - - /* Subseconds cannot be set.*/ - n = timespec->millisecond / 1000; - - /* Seconds conversion.*/ - tr = tr | ((n % 10) << RTC_TR_SU_OFFSET); - n /= 10; - tr = tr | ((n % 6) << RTC_TR_ST_OFFSET); - n /= 6; - - /* Minutes conversion.*/ - tr = tr | ((n % 10) << RTC_TR_MNU_OFFSET); - n /= 10; - tr = tr | ((n % 6) << RTC_TR_MNT_OFFSET); - n /= 6; - - /* Hours conversion.*/ - tr = tr | ((n % 10) << RTC_TR_HU_OFFSET); - n /= 10; - tr = tr | (n << RTC_TR_HT_OFFSET); - - return tr; -} - -/** - * @brief Converts a date from timespec to DR register encoding. - * - * @param[in] timespec pointer to a @p RTCDateTime structure - * @return the DR register encoding. - * - * @notapi - */ -static uint32_t rtc_encode_date(const RTCDateTime *timespec) { - uint32_t n, dr = 0; - - /* Year conversion. Note, only years last two digits are considered.*/ - n = timespec->year; - dr = dr | ((n % 10) << RTC_DR_YU_OFFSET); - n /= 10; - dr = dr | ((n % 10) << RTC_DR_YT_OFFSET); - - /* Months conversion.*/ - n = timespec->month; - dr = dr | ((n % 10) << RTC_DR_MU_OFFSET); - n /= 10; - dr = dr | ((n % 10) << RTC_DR_MT_OFFSET); - - /* Days conversion.*/ - n = timespec->day; - dr = dr | ((n % 10) << RTC_DR_DU_OFFSET); - n /= 10; - dr = dr | ((n % 10) << RTC_DR_DT_OFFSET); - - /* Days of week conversion.*/ - dr = dr | (timespec->dayofweek << RTC_DR_WDU_OFFSET); - - return dr; -} - -#if RTC_HAS_STORAGE == TRUE -static size_t _getsize(void *instance) { - - (void)instance; - - return (size_t)STM32_RTC_STORAGE_SIZE; -} - -static ps_error_t _read(void *instance, ps_offset_t offset, - size_t n, uint8_t *rp) { - volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R; - unsigned i; - - osalDbgCheck((instance != NULL) && (rp != NULL)); - osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); - osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && - (offset + n <= STM32_RTC_STORAGE_SIZE)); - - for (i = 0; i < (unsigned)n; i++) { - unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); - unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); - *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U)); - } - - return PS_NO_ERROR; -} - -static ps_error_t _write(void *instance, ps_offset_t offset, - size_t n, const uint8_t *wp) { - volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R; - unsigned i; - - osalDbgCheck((instance != NULL) && (wp != NULL)); - osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); - osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && - (offset + n <= STM32_RTC_STORAGE_SIZE)); - - for (i = 0; i < (unsigned)n; i++) { - unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); - unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); - uint32_t regval = bkpr[index]; - regval &= ~(0xFFU << (shift * 8U)); - regval |= (uint32_t)*wp++ << (shift * 8U); - bkpr[index] = regval; - } - - return PS_NO_ERROR; -} - -/** - * @brief VMT for the RTC storage file interface. - */ -struct RTCDriverVMT _rtc_lld_vmt = { - (size_t)0, - _getsize, _read, _write -}; -#endif /* RTC_HAS_STORAGE == TRUE */ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if defined(STM32_RTC_COMMON_HANDLER) -#if !defined(STM32_RTC_SUPPRESS_COMMON_ISR) -/** - * @brief RTC common interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_COMMON_HANDLER) { - uint32_t isr, clear; - - OSAL_IRQ_PROLOGUE(); - - clear = (0U - | RTC_ISR_TSF - | RTC_ISR_TSOVF -#if defined(RTC_ISR_TAMP1F) - | RTC_ISR_TAMP1F -#endif -#if defined(RTC_ISR_TAMP2F) - | RTC_ISR_TAMP2F -#endif -#if defined(RTC_ISR_TAMP3F) - | RTC_ISR_TAMP3F -#endif -#if defined(RTC_ISR_WUTF) - | RTC_ISR_WUTF -#endif -#if defined(RTC_ISR_ALRAF) - | RTC_ISR_ALRAF -#endif -#if defined(RTC_ISR_ALRBF) - | RTC_ISR_ALRBF -#endif - ); - - isr = RTCD1.rtc->ISR; - RTCD1.rtc->ISR = isr & ~clear; - - extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | - EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | - EXTI_MASK1(STM32_RTC_WKUP_EXTI)); - - if (RTCD1.callback != NULL) { - uint32_t cr = RTCD1.rtc->CR; - uint32_t tcr; - -#if defined(RTC_ISR_WUTF) - if (((cr & RTC_CR_WUTIE) != 0U) && ((isr & RTC_ISR_WUTF) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP); - } -#endif - -#if defined(RTC_ISR_ALRAF) - if (((cr & RTC_CR_ALRAIE) != 0U) && ((isr & RTC_ISR_ALRAF) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A); - } -#endif -#if defined(RTC_ISR_ALRBF) - if (((cr & RTC_CR_ALRBIE) != 0U) && ((isr & RTC_ISR_ALRBF) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B); - } -#endif - - if ((cr & RTC_CR_TSIE) != 0U) { - if ((isr & RTC_ISR_TSF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TS); - } - if ((isr & RTC_ISR_TSOVF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF); - } - } - - /* This part is different depending on if the RTC has a TAMPCR or TAFCR - register.*/ -#if defined(RTC_TAFCR_TAMP1E) - tcr = RTCD1.rtc->TAFCR; - if ((tcr & RTC_TAFCR_TAMPIE) != 0U) { -#if defined(RTC_ISR_TAMP1F) - if ((isr & RTC_ISR_TAMP1F) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); - } -#endif -#if defined(RTC_ISR_TAMP2F) - if ((isr & RTC_ISR_TAMP2F) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); - } -#endif - } - -#else /* !defined(RTC_TAFCR_TAMP1E) */ - tcr = RTCD1.rtc->TAMPCR; -#if defined(RTC_ISR_TAMP1F) - if (((tcr & RTC_TAMPCR_TAMP1IE) != 0U) && - ((isr & RTC_ISR_TAMP1F) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); - } -#endif -#if defined(RTC_ISR_TAMP2F) - if (((tcr & RTC_TAMPCR_TAMP2IE) != 0U) && - ((isr & RTC_ISR_TAMP2F) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); - } -#endif -#if defined(RTC_ISR_TAMP3F) - if (((tcr & RTC_TAMPCR_TAMP3IE) != 0U) && - ((isr & RTC_ISR_TAMP3F) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3); - } -#endif -#endif /* !defined(RTC_TAFCR_TAMP1E) */ - } - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_RTC_SUPPRESS_COMMON_ISR) */ - -#elif defined(STM32_RTC_TAMP_STAMP_HANDLER) && \ - defined(STM32_RTC_WKUP_HANDLER) && \ - defined(STM32_RTC_ALARM_HANDLER) -/** - * @brief RTC TAMP/STAMP interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_TAMP_STAMP_HANDLER) { - uint32_t isr, clear; - - OSAL_IRQ_PROLOGUE(); - - clear = (0U - | RTC_ISR_TSF - | RTC_ISR_TSOVF -#if defined(RTC_ISR_TAMP1F) - | RTC_ISR_TAMP1F -#endif -#if defined(RTC_ISR_TAMP2F) - | RTC_ISR_TAMP2F -#endif -#if defined(RTC_ISR_TAMP3F) - | RTC_ISR_TAMP3F -#endif - ); - - isr = RTCD1.rtc->ISR; - RTCD1.rtc->ISR = isr & ~clear; - - extiClearGroup1(EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI)); - - if (RTCD1.callback != NULL) { - uint32_t cr, tcr; - - cr = RTCD1.rtc->CR; - if ((cr & RTC_CR_TSIE) != 0U) { - if ((isr & RTC_ISR_TSF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TS); - } - if ((isr & RTC_ISR_TSOVF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF); - } - } - - /* This part is different depending on if the RTC has a TAMPCR or TAFCR - register.*/ -#if defined(RTC_TAFCR_TAMP1E) - tcr = RTCD1.rtc->TAFCR; - if ((tcr & RTC_TAFCR_TAMPIE) != 0U) { -#if defined(RTC_ISR_TAMP1F) - if ((isr & RTC_ISR_TAMP1F) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); - } -#endif -#if defined(RTC_ISR_TAMP2F) - if ((isr & RTC_ISR_TAMP2F) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); - } -#endif - } - -#else /* !defined(RTC_TAFCR_TAMP1E) */ - tcr = RTCD1.rtc->TAMPCR; -#if defined(RTC_ISR_TAMP1F) - if (((tcr & RTC_TAMPCR_TAMP1IE) != 0U) && - ((isr & RTC_ISR_TAMP1F) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); - } -#endif -#if defined(RTC_ISR_TAMP2F) - if (((tcr & RTC_TAMPCR_TAMP2IE) != 0U) && - ((isr & RTC_ISR_TAMP2F) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); - } -#endif -#if defined(RTC_ISR_TAMP3F) - if (((tcr & RTC_TAMPCR_TAMP3IE) != 0U) && - ((isr & RTC_ISR_TAMP3F) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3); - } -#endif -#endif /* !defined(RTC_TAFCR_TAMP1E) */ - } - - OSAL_IRQ_EPILOGUE(); -} -/** - * @brief RTC wakeup interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_WKUP_HANDLER) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = RTCD1.rtc->ISR; - RTCD1.rtc->ISR = isr & ~RTC_ISR_WUTF; - - extiClearGroup1(EXTI_MASK1(STM32_RTC_WKUP_EXTI)); - - if (RTCD1.callback != NULL) { - uint32_t cr = RTCD1.rtc->CR; - - if (((cr & RTC_CR_WUTIE) != 0U) && ((isr & RTC_ISR_WUTF) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP); - } - } - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief RTC alarm interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_ALARM_HANDLER) { - uint32_t isr, clear; - - OSAL_IRQ_PROLOGUE(); - - clear = (0U -#if defined(RTC_ISR_ALRAF) - | RTC_ISR_ALRAF -#endif -#if defined(RTC_ISR_ALRBF) - | RTC_ISR_ALRBF -#endif - ); - - isr = RTCD1.rtc->ISR; - RTCD1.rtc->ISR = isr & ~clear; - - extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI)); - - if (RTCD1.callback != NULL) { - uint32_t cr = RTCD1.rtc->CR; -#if defined(RTC_ISR_ALRAF) - if (((cr & RTC_CR_ALRAIE) != 0U) && ((isr & RTC_ISR_ALRAF) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A); - } -#endif -#if defined(RTC_ISR_ALRBF) - if (((cr & RTC_CR_ALRBIE) != 0U) && ((isr & RTC_ISR_ALRBF) != 0U)) { - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B); - } -#endif - } - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "missing required RTC handlers definitions in registry" -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enable access to registers. - * - * @notapi - */ -void rtc_lld_init(void) { - - /* RTC object initialization.*/ - rtcObjectInit(&RTCD1); - - /* RTC pointer initialization.*/ - RTCD1.rtc = RTC; - - /* Disable write protection. */ - RTCD1.rtc->WPR = 0xCA; - RTCD1.rtc->WPR = 0x53; - - /* If calendar has not been initialized yet then proceed with the - initial setup.*/ - if (!(RTCD1.rtc->ISR & RTC_ISR_INITS)) { - - rtc_enter_init(); - - RTCD1.rtc->CR = STM32_RTC_CR_INIT; -#if defined(RTC_TAFCR_TAMP1E) - RTCD1.rtc->TAFCR = STM32_RTC_TAMPCR_INIT; -#else - RTCD1.rtc->TAMPCR = STM32_RTC_TAMPCR_INIT; -#endif - RTCD1.rtc->ISR = RTC_ISR_INIT; /* Clearing all but RTC_ISR_INIT. */ - RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; - RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; - - rtc_exit_init(); - } - else { - RTCD1.rtc->ISR &= ~RTC_ISR_RSF; - } - - /* Callback initially disabled.*/ - RTCD1.callback = NULL; - - /* Enabling RTC-related EXTI lines.*/ - extiEnableGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | - EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | - EXTI_MASK1(STM32_RTC_WKUP_EXTI), - EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); - - /* IRQ vectors permanently assigned to this driver.*/ - STM32_RTC_IRQ_ENABLE(); -} - -/** - * @brief Set current time. - * @note Fractional part will be silently ignored. There is no possibility - * to set it on STM32 platform. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { - uint32_t dr, tr; - syssts_t sts; - - tr = rtc_encode_time(timespec); - dr = rtc_encode_date(timespec); - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - /* Writing the registers.*/ - rtc_enter_init(); - rtcp->rtc->TR = tr; - rtcp->rtc->DR = dr; - rtcp->rtc->CR = (rtcp->rtc->CR & ~(1U << RTC_CR_BKP_OFFSET)) | - (timespec->dstflag << RTC_CR_BKP_OFFSET); - rtc_exit_init(); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Get current time. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { - uint32_t dr, tr, cr; - uint32_t subs; -#if STM32_RTC_HAS_SUBSECONDS - uint32_t oldssr, ssr; -#endif /* STM32_RTC_HAS_SUBSECONDS */ - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - /* Synchronization with the RTC and reading the registers, note - DR must be read last.*/ - while ((rtcp->rtc->ISR & RTC_ISR_RSF) == 0) - ; -#if STM32_RTC_HAS_SUBSECONDS - oldssr = rtcp->rtc->SSR; - do -#endif /* STM32_RTC_HAS_SUBSECONDS */ - { - tr = rtcp->rtc->TR; - dr = rtcp->rtc->DR; - cr = rtcp->rtc->CR; - } -#if STM32_RTC_HAS_SUBSECONDS - while (oldssr != (ssr = rtcp->rtc->SSR)); -#endif /* STM32_RTC_HAS_SUBSECONDS */ - rtcp->rtc->ISR &= ~RTC_ISR_RSF; - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); - - /* Decoding day time, this starts the atomic read sequence, see "Reading - the calendar" in the RTC documentation.*/ - rtc_decode_time(tr, timespec); - - /* If the RTC is capable of sub-second counting then the value is - normalized in milliseconds and added to the time.*/ -#if STM32_RTC_HAS_SUBSECONDS - subs = (((STM32_RTC_PRESS_VALUE - 1U) - ssr) * 1000U) / STM32_RTC_PRESS_VALUE; -#else - subs = 0; -#endif /* STM32_RTC_HAS_SUBSECONDS */ - timespec->millisecond += subs; - - /* Decoding date, this concludes the atomic read sequence.*/ - rtc_decode_date(dr, timespec); - - /* Retrieving the DST bit.*/ - timespec->dstflag = (cr >> RTC_CR_BKP_OFFSET) & 1; -} - -#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) -/** - * @brief Set alarm time. - * @note Default value after BKP domain reset for both comparators is 0. - * @note Function does not performs any checks of alarm time validity. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure. - * @param[in] alarm alarm identifier. Can be 0 or 1. - * @param[in] alarmspec pointer to a @p RTCAlarm structure. - * - * @notapi - */ -void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - if (alarm == 0) { - if (alarmspec != NULL) { - rtcp->rtc->CR &= ~RTC_CR_ALRAE; - while (!(rtcp->rtc->ISR & RTC_ISR_ALRAWF)) - ; - rtcp->rtc->ALRMAR = alarmspec->alrmr; - rtcp->rtc->CR |= RTC_CR_ALRAE; - rtcp->rtc->CR |= RTC_CR_ALRAIE; - } - else { - rtcp->rtc->CR &= ~RTC_CR_ALRAIE; - rtcp->rtc->CR &= ~RTC_CR_ALRAE; - } - } -#if RTC_ALARMS > 1 - else { - if (alarmspec != NULL) { - rtcp->rtc->CR &= ~RTC_CR_ALRBE; - while (!(rtcp->rtc->ISR & RTC_ISR_ALRBWF)) - ; - rtcp->rtc->ALRMBR = alarmspec->alrmr; - rtcp->rtc->CR |= RTC_CR_ALRBE; - rtcp->rtc->CR |= RTC_CR_ALRBIE; - } - else { - rtcp->rtc->CR &= ~RTC_CR_ALRBIE; - rtcp->rtc->CR &= ~RTC_CR_ALRBE; - } - } -#endif /* RTC_ALARMS > 1 */ - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Get alarm time. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier. Can be 0 or 1. - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ -void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec) { - - if (alarm == 0) - alarmspec->alrmr = rtcp->rtc->ALRMAR; -#if RTC_ALARMS > 1 - else - alarmspec->alrmr = rtcp->rtc->ALRMBR; -#endif /* RTC_ALARMS > 1 */ -} -#endif /* RTC_ALARMS > 0 */ - -/** - * @brief Enables or disables RTC callbacks. - * @details This function enables or disables callbacks, use a @p NULL pointer - * in order to disable a callback. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL - * - * @notapi - */ -void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { - - rtcp->callback = callback; -} - -#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__) -/** - * @brief Sets time of periodic wakeup. - * @note Default value after BKP domain reset is 0x0000FFFF - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] wakeupspec pointer to a @p RTCWakeup structure - * - * @api - */ -void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - if (wakeupspec != NULL) { - osalDbgCheck(wakeupspec->wutr != 0x30000); - - rtcp->rtc->CR &= ~RTC_CR_WUTE; - rtcp->rtc->CR &= ~RTC_CR_WUTIE; - while (!(rtcp->rtc->ISR & RTC_ISR_WUTWF)) - ; - rtcp->rtc->WUTR = wakeupspec->wutr & 0xFFFF; - rtcp->rtc->CR &= ~RTC_CR_WUCKSEL; - rtcp->rtc->CR |= (wakeupspec->wutr >> 16) & RTC_CR_WUCKSEL; - rtcp->rtc->CR |= RTC_CR_WUTIE; - rtcp->rtc->CR |= RTC_CR_WUTE; - } - else { - rtcp->rtc->CR &= ~RTC_CR_WUTE; - rtcp->rtc->CR &= ~RTC_CR_WUTIE; - } - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Gets time of periodic wakeup. - * @note Default value after BKP domain reset is 0x0000FFFF - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] wakeupspec pointer to a @p RTCWakeup structure - * - * @api - */ -void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - wakeupspec->wutr = 0; - wakeupspec->wutr |= rtcp->rtc->WUTR; - wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16; - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} -#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ - -#endif /* HAL_USE_RTC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv2/hal_rtc_lld.c + * @brief STM32 RTC low level driver. + * + * @addtogroup RTC + * @{ + */ + +#include "hal.h" + +// If you enable subseconds, there is a chance that this code will hang while locked (!) +// See https://github.com/rusefi/rusefi/issues/4557 +#undef STM32_RTC_HAS_SUBSECONDS +#define STM32_RTC_HAS_SUBSECONDS FALSE + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define RTC_TR_PM_OFFSET 22 +#define RTC_TR_HT_OFFSET 20 +#define RTC_TR_HU_OFFSET 16 +#define RTC_TR_MNT_OFFSET 12 +#define RTC_TR_MNU_OFFSET 8 +#define RTC_TR_ST_OFFSET 4 +#define RTC_TR_SU_OFFSET 0 + +#define RTC_DR_YT_OFFSET 20 +#define RTC_DR_YU_OFFSET 16 +#define RTC_DR_WDU_OFFSET 13 +#define RTC_DR_MT_OFFSET 12 +#define RTC_DR_MU_OFFSET 8 +#define RTC_DR_DT_OFFSET 4 +#define RTC_DR_DU_OFFSET 0 + +#define RTC_CR_BKP_OFFSET 18 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Beginning of configuration procedure. + * + * @notapi + */ +static void rtc_enter_init(void) { + + RTCD1.rtc->ISR |= RTC_ISR_INIT; + while ((RTCD1.rtc->ISR & RTC_ISR_INITF) == 0) + ; +} + +/** + * @brief Finalizing of configuration procedure. + * + * @notapi + */ +static inline void rtc_exit_init(void) { + + RTCD1.rtc->ISR &= ~RTC_ISR_INIT; +} + +/** + * @brief Converts time from TR register encoding to timespec. + * + * @param[in] tr TR register value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +static void rtc_decode_time(uint32_t tr, RTCDateTime *timespec) { + uint32_t n; + + n = ((tr >> RTC_TR_HT_OFFSET) & 3) * 36000000; + n += ((tr >> RTC_TR_HU_OFFSET) & 15) * 3600000; + n += ((tr >> RTC_TR_MNT_OFFSET) & 7) * 600000; + n += ((tr >> RTC_TR_MNU_OFFSET) & 15) * 60000; + n += ((tr >> RTC_TR_ST_OFFSET) & 7) * 10000; + n += ((tr >> RTC_TR_SU_OFFSET) & 15) * 1000; + timespec->millisecond = n; +} + +/** + * @brief Converts date from DR register encoding to timespec. + * + * @param[in] dr DR register value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +static void rtc_decode_date(uint32_t dr, RTCDateTime *timespec) { + + timespec->year = (((dr >> RTC_DR_YT_OFFSET) & 15) * 10) + + ((dr >> RTC_DR_YU_OFFSET) & 15); + timespec->month = (((dr >> RTC_TR_MNT_OFFSET) & 1) * 10) + + ((dr >> RTC_TR_MNU_OFFSET) & 15); + timespec->day = (((dr >> RTC_DR_DT_OFFSET) & 3) * 10) + + ((dr >> RTC_DR_DU_OFFSET) & 15); + timespec->dayofweek = (dr >> RTC_DR_WDU_OFFSET) & 7; +} + +/** + * @brief Converts time from timespec to TR register encoding. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @return the TR register encoding. + * + * @notapi + */ +static uint32_t rtc_encode_time(const RTCDateTime *timespec) { + uint32_t n, tr = 0; + + /* Subseconds cannot be set.*/ + n = timespec->millisecond / 1000; + + /* Seconds conversion.*/ + tr = tr | ((n % 10) << RTC_TR_SU_OFFSET); + n /= 10; + tr = tr | ((n % 6) << RTC_TR_ST_OFFSET); + n /= 6; + + /* Minutes conversion.*/ + tr = tr | ((n % 10) << RTC_TR_MNU_OFFSET); + n /= 10; + tr = tr | ((n % 6) << RTC_TR_MNT_OFFSET); + n /= 6; + + /* Hours conversion.*/ + tr = tr | ((n % 10) << RTC_TR_HU_OFFSET); + n /= 10; + tr = tr | (n << RTC_TR_HT_OFFSET); + + return tr; +} + +/** + * @brief Converts a date from timespec to DR register encoding. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @return the DR register encoding. + * + * @notapi + */ +static uint32_t rtc_encode_date(const RTCDateTime *timespec) { + uint32_t n, dr = 0; + + /* Year conversion. Note, only years last two digits are considered.*/ + n = timespec->year; + dr = dr | ((n % 10) << RTC_DR_YU_OFFSET); + n /= 10; + dr = dr | ((n % 10) << RTC_DR_YT_OFFSET); + + /* Months conversion.*/ + n = timespec->month; + dr = dr | ((n % 10) << RTC_DR_MU_OFFSET); + n /= 10; + dr = dr | ((n % 10) << RTC_DR_MT_OFFSET); + + /* Days conversion.*/ + n = timespec->day; + dr = dr | ((n % 10) << RTC_DR_DU_OFFSET); + n /= 10; + dr = dr | ((n % 10) << RTC_DR_DT_OFFSET); + + /* Days of week conversion.*/ + dr = dr | (timespec->dayofweek << RTC_DR_WDU_OFFSET); + + return dr; +} + +#if RTC_HAS_STORAGE == TRUE +static size_t _getsize(void *instance) { + + (void)instance; + + return (size_t)STM32_RTC_STORAGE_SIZE; +} + +static ps_error_t _read(void *instance, ps_offset_t offset, + size_t n, uint8_t *rp) { + volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R; + unsigned i; + + osalDbgCheck((instance != NULL) && (rp != NULL)); + osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); + osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && + (offset + n <= STM32_RTC_STORAGE_SIZE)); + + for (i = 0; i < (unsigned)n; i++) { + unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); + unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); + *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U)); + } + + return PS_NO_ERROR; +} + +static ps_error_t _write(void *instance, ps_offset_t offset, + size_t n, const uint8_t *wp) { + volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R; + unsigned i; + + osalDbgCheck((instance != NULL) && (wp != NULL)); + osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); + osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && + (offset + n <= STM32_RTC_STORAGE_SIZE)); + + for (i = 0; i < (unsigned)n; i++) { + unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); + unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); + uint32_t regval = bkpr[index]; + regval &= ~(0xFFU << (shift * 8U)); + regval |= (uint32_t)*wp++ << (shift * 8U); + bkpr[index] = regval; + } + + return PS_NO_ERROR; +} + +/** + * @brief VMT for the RTC storage file interface. + */ +struct RTCDriverVMT _rtc_lld_vmt = { + (size_t)0, + _getsize, _read, _write +}; +#endif /* RTC_HAS_STORAGE == TRUE */ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if defined(STM32_RTC_COMMON_HANDLER) +#if !defined(STM32_RTC_SUPPRESS_COMMON_ISR) +/** + * @brief RTC common interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_COMMON_HANDLER) { + uint32_t isr, clear; + + OSAL_IRQ_PROLOGUE(); + + clear = (0U + | RTC_ISR_TSF + | RTC_ISR_TSOVF +#if defined(RTC_ISR_TAMP1F) + | RTC_ISR_TAMP1F +#endif +#if defined(RTC_ISR_TAMP2F) + | RTC_ISR_TAMP2F +#endif +#if defined(RTC_ISR_TAMP3F) + | RTC_ISR_TAMP3F +#endif +#if defined(RTC_ISR_WUTF) + | RTC_ISR_WUTF +#endif +#if defined(RTC_ISR_ALRAF) + | RTC_ISR_ALRAF +#endif +#if defined(RTC_ISR_ALRBF) + | RTC_ISR_ALRBF +#endif + ); + + isr = RTCD1.rtc->ISR; + RTCD1.rtc->ISR = isr & ~clear; + + extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | + EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | + EXTI_MASK1(STM32_RTC_WKUP_EXTI)); + + if (RTCD1.callback != NULL) { + uint32_t cr = RTCD1.rtc->CR; + uint32_t tcr; + +#if defined(RTC_ISR_WUTF) + if (((cr & RTC_CR_WUTIE) != 0U) && ((isr & RTC_ISR_WUTF) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP); + } +#endif + +#if defined(RTC_ISR_ALRAF) + if (((cr & RTC_CR_ALRAIE) != 0U) && ((isr & RTC_ISR_ALRAF) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A); + } +#endif +#if defined(RTC_ISR_ALRBF) + if (((cr & RTC_CR_ALRBIE) != 0U) && ((isr & RTC_ISR_ALRBF) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B); + } +#endif + + if ((cr & RTC_CR_TSIE) != 0U) { + if ((isr & RTC_ISR_TSF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TS); + } + if ((isr & RTC_ISR_TSOVF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF); + } + } + + /* This part is different depending on if the RTC has a TAMPCR or TAFCR + register.*/ +#if defined(RTC_TAFCR_TAMP1E) + tcr = RTCD1.rtc->TAFCR; + if ((tcr & RTC_TAFCR_TAMPIE) != 0U) { +#if defined(RTC_ISR_TAMP1F) + if ((isr & RTC_ISR_TAMP1F) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); + } +#endif +#if defined(RTC_ISR_TAMP2F) + if ((isr & RTC_ISR_TAMP2F) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); + } +#endif + } + +#else /* !defined(RTC_TAFCR_TAMP1E) */ + tcr = RTCD1.rtc->TAMPCR; +#if defined(RTC_ISR_TAMP1F) + if (((tcr & RTC_TAMPCR_TAMP1IE) != 0U) && + ((isr & RTC_ISR_TAMP1F) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); + } +#endif +#if defined(RTC_ISR_TAMP2F) + if (((tcr & RTC_TAMPCR_TAMP2IE) != 0U) && + ((isr & RTC_ISR_TAMP2F) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); + } +#endif +#if defined(RTC_ISR_TAMP3F) + if (((tcr & RTC_TAMPCR_TAMP3IE) != 0U) && + ((isr & RTC_ISR_TAMP3F) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3); + } +#endif +#endif /* !defined(RTC_TAFCR_TAMP1E) */ + } + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_RTC_SUPPRESS_COMMON_ISR) */ + +#elif defined(STM32_RTC_TAMP_STAMP_HANDLER) && \ + defined(STM32_RTC_WKUP_HANDLER) && \ + defined(STM32_RTC_ALARM_HANDLER) +/** + * @brief RTC TAMP/STAMP interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_TAMP_STAMP_HANDLER) { + uint32_t isr, clear; + + OSAL_IRQ_PROLOGUE(); + + clear = (0U + | RTC_ISR_TSF + | RTC_ISR_TSOVF +#if defined(RTC_ISR_TAMP1F) + | RTC_ISR_TAMP1F +#endif +#if defined(RTC_ISR_TAMP2F) + | RTC_ISR_TAMP2F +#endif +#if defined(RTC_ISR_TAMP3F) + | RTC_ISR_TAMP3F +#endif + ); + + isr = RTCD1.rtc->ISR; + RTCD1.rtc->ISR = isr & ~clear; + + extiClearGroup1(EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI)); + + if (RTCD1.callback != NULL) { + uint32_t cr, tcr; + + cr = RTCD1.rtc->CR; + if ((cr & RTC_CR_TSIE) != 0U) { + if ((isr & RTC_ISR_TSF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TS); + } + if ((isr & RTC_ISR_TSOVF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF); + } + } + + /* This part is different depending on if the RTC has a TAMPCR or TAFCR + register.*/ +#if defined(RTC_TAFCR_TAMP1E) + tcr = RTCD1.rtc->TAFCR; + if ((tcr & RTC_TAFCR_TAMPIE) != 0U) { +#if defined(RTC_ISR_TAMP1F) + if ((isr & RTC_ISR_TAMP1F) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); + } +#endif +#if defined(RTC_ISR_TAMP2F) + if ((isr & RTC_ISR_TAMP2F) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); + } +#endif + } + +#else /* !defined(RTC_TAFCR_TAMP1E) */ + tcr = RTCD1.rtc->TAMPCR; +#if defined(RTC_ISR_TAMP1F) + if (((tcr & RTC_TAMPCR_TAMP1IE) != 0U) && + ((isr & RTC_ISR_TAMP1F) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); + } +#endif +#if defined(RTC_ISR_TAMP2F) + if (((tcr & RTC_TAMPCR_TAMP2IE) != 0U) && + ((isr & RTC_ISR_TAMP2F) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); + } +#endif +#if defined(RTC_ISR_TAMP3F) + if (((tcr & RTC_TAMPCR_TAMP3IE) != 0U) && + ((isr & RTC_ISR_TAMP3F) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3); + } +#endif +#endif /* !defined(RTC_TAFCR_TAMP1E) */ + } + + OSAL_IRQ_EPILOGUE(); +} +/** + * @brief RTC wakeup interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_WKUP_HANDLER) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = RTCD1.rtc->ISR; + RTCD1.rtc->ISR = isr & ~RTC_ISR_WUTF; + + extiClearGroup1(EXTI_MASK1(STM32_RTC_WKUP_EXTI)); + + if (RTCD1.callback != NULL) { + uint32_t cr = RTCD1.rtc->CR; + + if (((cr & RTC_CR_WUTIE) != 0U) && ((isr & RTC_ISR_WUTF) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP); + } + } + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief RTC alarm interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_ALARM_HANDLER) { + uint32_t isr, clear; + + OSAL_IRQ_PROLOGUE(); + + clear = (0U +#if defined(RTC_ISR_ALRAF) + | RTC_ISR_ALRAF +#endif +#if defined(RTC_ISR_ALRBF) + | RTC_ISR_ALRBF +#endif + ); + + isr = RTCD1.rtc->ISR; + RTCD1.rtc->ISR = isr & ~clear; + + extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI)); + + if (RTCD1.callback != NULL) { + uint32_t cr = RTCD1.rtc->CR; +#if defined(RTC_ISR_ALRAF) + if (((cr & RTC_CR_ALRAIE) != 0U) && ((isr & RTC_ISR_ALRAF) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A); + } +#endif +#if defined(RTC_ISR_ALRBF) + if (((cr & RTC_CR_ALRBIE) != 0U) && ((isr & RTC_ISR_ALRBF) != 0U)) { + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B); + } +#endif + } + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "missing required RTC handlers definitions in registry" +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enable access to registers. + * + * @notapi + */ +void rtc_lld_init(void) { + + /* RTC object initialization.*/ + rtcObjectInit(&RTCD1); + + /* RTC pointer initialization.*/ + RTCD1.rtc = RTC; + + /* Disable write protection. */ + RTCD1.rtc->WPR = 0xCA; + RTCD1.rtc->WPR = 0x53; + + /* If calendar has not been initialized yet then proceed with the + initial setup.*/ + if (!(RTCD1.rtc->ISR & RTC_ISR_INITS)) { + + rtc_enter_init(); + + RTCD1.rtc->CR = STM32_RTC_CR_INIT; +#if defined(RTC_TAFCR_TAMP1E) + RTCD1.rtc->TAFCR = STM32_RTC_TAMPCR_INIT; +#else + RTCD1.rtc->TAMPCR = STM32_RTC_TAMPCR_INIT; +#endif + RTCD1.rtc->ISR = RTC_ISR_INIT; /* Clearing all but RTC_ISR_INIT. */ + RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; + RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; + + rtc_exit_init(); + } + else { + RTCD1.rtc->ISR &= ~RTC_ISR_RSF; + } + + /* Callback initially disabled.*/ + RTCD1.callback = NULL; + + /* Enabling RTC-related EXTI lines.*/ + extiEnableGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | + EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | + EXTI_MASK1(STM32_RTC_WKUP_EXTI), + EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); + + /* IRQ vectors permanently assigned to this driver.*/ + STM32_RTC_IRQ_ENABLE(); +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to set it on STM32 platform. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { + uint32_t dr, tr; + syssts_t sts; + + tr = rtc_encode_time(timespec); + dr = rtc_encode_date(timespec); + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + /* Writing the registers.*/ + rtc_enter_init(); + rtcp->rtc->TR = tr; + rtcp->rtc->DR = dr; + rtcp->rtc->CR = (rtcp->rtc->CR & ~(1U << RTC_CR_BKP_OFFSET)) | + (timespec->dstflag << RTC_CR_BKP_OFFSET); + rtc_exit_init(); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Get current time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { + uint32_t dr, tr, cr; + uint32_t subs; +#if STM32_RTC_HAS_SUBSECONDS + uint32_t oldssr, ssr; +#endif /* STM32_RTC_HAS_SUBSECONDS */ + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + /* Synchronization with the RTC and reading the registers, note + DR must be read last.*/ + while ((rtcp->rtc->ISR & RTC_ISR_RSF) == 0) + ; +#if STM32_RTC_HAS_SUBSECONDS + oldssr = rtcp->rtc->SSR; + do +#endif /* STM32_RTC_HAS_SUBSECONDS */ + { + tr = rtcp->rtc->TR; + dr = rtcp->rtc->DR; + cr = rtcp->rtc->CR; + } +#if STM32_RTC_HAS_SUBSECONDS + while (oldssr != (ssr = rtcp->rtc->SSR)); +#endif /* STM32_RTC_HAS_SUBSECONDS */ + rtcp->rtc->ISR &= ~RTC_ISR_RSF; + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); + + /* Decoding day time, this starts the atomic read sequence, see "Reading + the calendar" in the RTC documentation.*/ + rtc_decode_time(tr, timespec); + + /* If the RTC is capable of sub-second counting then the value is + normalized in milliseconds and added to the time.*/ +#if STM32_RTC_HAS_SUBSECONDS + subs = (((STM32_RTC_PRESS_VALUE - 1U) - ssr) * 1000U) / STM32_RTC_PRESS_VALUE; +#else + subs = 0; +#endif /* STM32_RTC_HAS_SUBSECONDS */ + timespec->millisecond += subs; + + /* Decoding date, this concludes the atomic read sequence.*/ + rtc_decode_date(dr, timespec); + + /* Retrieving the DST bit.*/ + timespec->dstflag = (cr >> RTC_CR_BKP_OFFSET) & 1; +} + +#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) +/** + * @brief Set alarm time. + * @note Default value after BKP domain reset for both comparators is 0. + * @note Function does not performs any checks of alarm time validity. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure. + * @param[in] alarm alarm identifier. Can be 0 or 1. + * @param[in] alarmspec pointer to a @p RTCAlarm structure. + * + * @notapi + */ +void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + if (alarm == 0) { + if (alarmspec != NULL) { + rtcp->rtc->CR &= ~RTC_CR_ALRAE; + while (!(rtcp->rtc->ISR & RTC_ISR_ALRAWF)) + ; + rtcp->rtc->ALRMAR = alarmspec->alrmr; + rtcp->rtc->CR |= RTC_CR_ALRAE; + rtcp->rtc->CR |= RTC_CR_ALRAIE; + } + else { + rtcp->rtc->CR &= ~RTC_CR_ALRAIE; + rtcp->rtc->CR &= ~RTC_CR_ALRAE; + } + } +#if RTC_ALARMS > 1 + else { + if (alarmspec != NULL) { + rtcp->rtc->CR &= ~RTC_CR_ALRBE; + while (!(rtcp->rtc->ISR & RTC_ISR_ALRBWF)) + ; + rtcp->rtc->ALRMBR = alarmspec->alrmr; + rtcp->rtc->CR |= RTC_CR_ALRBE; + rtcp->rtc->CR |= RTC_CR_ALRBIE; + } + else { + rtcp->rtc->CR &= ~RTC_CR_ALRBIE; + rtcp->rtc->CR &= ~RTC_CR_ALRBE; + } + } +#endif /* RTC_ALARMS > 1 */ + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Get alarm time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier. Can be 0 or 1. + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + + if (alarm == 0) + alarmspec->alrmr = rtcp->rtc->ALRMAR; +#if RTC_ALARMS > 1 + else + alarmspec->alrmr = rtcp->rtc->ALRMBR; +#endif /* RTC_ALARMS > 1 */ +} +#endif /* RTC_ALARMS > 0 */ + +/** + * @brief Enables or disables RTC callbacks. + * @details This function enables or disables callbacks, use a @p NULL pointer + * in order to disable a callback. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] callback callback function pointer or @p NULL + * + * @notapi + */ +void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { + + rtcp->callback = callback; +} + +#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__) +/** + * @brief Sets time of periodic wakeup. + * @note Default value after BKP domain reset is 0x0000FFFF + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] wakeupspec pointer to a @p RTCWakeup structure + * + * @api + */ +void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + if (wakeupspec != NULL) { + osalDbgCheck(wakeupspec->wutr != 0x30000); + + rtcp->rtc->CR &= ~RTC_CR_WUTE; + rtcp->rtc->CR &= ~RTC_CR_WUTIE; + while (!(rtcp->rtc->ISR & RTC_ISR_WUTWF)) + ; + rtcp->rtc->WUTR = wakeupspec->wutr & 0xFFFF; + rtcp->rtc->CR &= ~RTC_CR_WUCKSEL; + rtcp->rtc->CR |= (wakeupspec->wutr >> 16) & RTC_CR_WUCKSEL; + rtcp->rtc->CR |= RTC_CR_WUTIE; + rtcp->rtc->CR |= RTC_CR_WUTE; + } + else { + rtcp->rtc->CR &= ~RTC_CR_WUTE; + rtcp->rtc->CR &= ~RTC_CR_WUTIE; + } + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Gets time of periodic wakeup. + * @note Default value after BKP domain reset is 0x0000FFFF + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] wakeupspec pointer to a @p RTCWakeup structure + * + * @api + */ +void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + wakeupspec->wutr = 0; + wakeupspec->wutr |= rtcp->rtc->WUTR; + wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16; + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} +#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ + +#endif /* HAL_USE_RTC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h index f60e798465..b25580834a 100644 --- a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h +++ b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h @@ -1,249 +1,249 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file RTCv2/hal_rtc_lld.h - * @brief STM32 RTC low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#ifndef HAL_RTC_LLD_H -#define HAL_RTC_LLD_H - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Implementation capabilities - */ -/** - * @brief Callback support int the driver. - */ -#define RTC_SUPPORTS_CALLBACKS TRUE - -/** - * @brief Number of alarms available. - */ -#define RTC_ALARMS STM32_RTC_NUM_ALARMS - -/** - * @brief Presence of a local persistent storage. - */ -#define RTC_HAS_STORAGE (STM32_RTC_STORAGE_SIZE > 0) -/** @} */ - -/** - * @brief RTC PRER register initializer. - */ -#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1)) - -/** - * @name Alarm helper macros - * @{ - */ -#define RTC_ALRM_MSK4 (1U << 31) -#define RTC_ALRM_WDSEL (1U << 30) -#define RTC_ALRM_DT(n) ((n) << 28) -#define RTC_ALRM_DU(n) ((n) << 24) -#define RTC_ALRM_MSK3 (1U << 23) -#define RTC_ALRM_HT(n) ((n) << 20) -#define RTC_ALRM_HU(n) ((n) << 16) -#define RTC_ALRM_MSK2 (1U << 15) -#define RTC_ALRM_MNT(n) ((n) << 12) -#define RTC_ALRM_MNU(n) ((n) << 8) -#define RTC_ALRM_MSK1 (1U << 7) -#define RTC_ALRM_ST(n) ((n) << 4) -#define RTC_ALRM_SU(n) ((n) << 0) -/** @} */ - -/* Requires services from the EXTI driver.*/ -#if !defined(STM32_EXTI_REQUIRED) -#define STM32_EXTI_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief RTC PRES register initialization. - * @note The default is calculated for a 32768Hz clock. - */ -#if !defined(STM32_RTC_PRESA_VALUE) || defined(__DOXYGEN__) -#define STM32_RTC_PRESA_VALUE 32 -#endif - -/** - * @brief RTC PRESS divider initialization. - * @note The default is calculated for a 32768Hz clock. - */ -#if !defined(STM32_RTC_PRESS_VALUE) || defined(__DOXYGEN__) -#define STM32_RTC_PRESS_VALUE 1024 -#endif - -/** - * @brief RTC CR register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - */ -#if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__) -#define STM32_RTC_CR_INIT 0 -#endif - -/** - * @brief RTC TAMPCR register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - * @note On some devices this values goes in the similar TAFCR register. - */ -#if !defined(STM32_RTC_TAMPCR_INIT) || defined(__DOXYGEN__) -#define STM32_RTC_TAMPCR_INIT 0 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if HAL_USE_RTC && !STM32_HAS_RTC -#error "RTC not present in the selected device" -#endif - -#if defined(STM32_RTC_CK) && !defined(STM32_RTCCLK) -#define STM32_RTCCLK STM32_RTC_CK -#endif - -#if !defined(STM32_RTCCLK) -#error "RTC clock not exported by HAL layer" -#endif - -#if STM32_PCLK1 < (STM32_RTCCLK * 7) -#error "STM32_PCLK1 frequency is too low" -#endif - -/** - * @brief Initialization for the RTC_PRER register. - */ -#define STM32_RTC_PRER_BITS RTC_PRER(STM32_RTC_PRESA_VALUE, \ - STM32_RTC_PRESS_VALUE) - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an RTC event. - */ -typedef enum { - RTC_EVENT_ALARM_A = 0, /** Alarm A. */ - RTC_EVENT_ALARM_B = 1, /** Alarm B. */ - RTC_EVENT_TS = 2, /** Time stamp. */ - RTC_EVENT_TS_OVF = 3, /** Time stamp overflow. */ - RTC_EVENT_TAMP1 = 4, /** Tamper 1. */ - RTC_EVENT_TAMP2 = 5, /** Tamper 2- */ - RTC_EVENT_TAMP3 = 6, /** Tamper 3. */ - RTC_EVENT_WAKEUP = 7 /** Wakeup. */ - } rtcevent_t; - -/** - * @brief Type of a generic RTC callback. - */ -typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); - -/** - * @brief Type of a structure representing an RTC alarm time stamp. - */ -typedef struct hal_rtc_alarm { - /** - * @brief Type of an alarm as encoded in RTC ALRMxR registers. - */ - uint32_t alrmr; -} RTCAlarm; - -#if STM32_RTC_HAS_PERIODIC_WAKEUPS -/** - * @brief Type of a wakeup as encoded in RTC WUTR register. - */ -typedef struct hal_rtc_wakeup { - /** - * @brief Wakeup as encoded in RTC WUTR register. - * @note ((WUTR == 0) || (WUCKSEL == 3)) are a forbidden combination. - * @note Bits 16..18 are copied in the CR bits 0..2 (WUCKSEL). - */ - uint32_t wutr; -} RTCWakeup; -#endif - -/** - * @brief Implementation-specific @p RTCDriver fields. - */ -#define rtc_lld_driver_fields \ - /* Pointer to the RTC registers block.*/ \ - RTC_TypeDef *rtc; \ - /* Callback pointer.*/ \ - rtccb_t callback - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void rtc_lld_init(void); - void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); - void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); -#if RTC_SUPPORTS_CALLBACKS == TRUE - void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); -#endif -#if RTC_ALARMS > 0 - void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec); - void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec); -#endif -#if STM32_RTC_HAS_PERIODIC_WAKEUPS - void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec); - void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec); -#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_RTC */ - -#endif /* HAL_RTC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv2/hal_rtc_lld.h + * @brief STM32 RTC low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef HAL_RTC_LLD_H +#define HAL_RTC_LLD_H + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Implementation capabilities + */ +/** + * @brief Callback support int the driver. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief Number of alarms available. + */ +#define RTC_ALARMS STM32_RTC_NUM_ALARMS + +/** + * @brief Presence of a local persistent storage. + */ +#define RTC_HAS_STORAGE (STM32_RTC_STORAGE_SIZE > 0) +/** @} */ + +/** + * @brief RTC PRER register initializer. + */ +#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1)) + +/** + * @name Alarm helper macros + * @{ + */ +#define RTC_ALRM_MSK4 (1U << 31) +#define RTC_ALRM_WDSEL (1U << 30) +#define RTC_ALRM_DT(n) ((n) << 28) +#define RTC_ALRM_DU(n) ((n) << 24) +#define RTC_ALRM_MSK3 (1U << 23) +#define RTC_ALRM_HT(n) ((n) << 20) +#define RTC_ALRM_HU(n) ((n) << 16) +#define RTC_ALRM_MSK2 (1U << 15) +#define RTC_ALRM_MNT(n) ((n) << 12) +#define RTC_ALRM_MNU(n) ((n) << 8) +#define RTC_ALRM_MSK1 (1U << 7) +#define RTC_ALRM_ST(n) ((n) << 4) +#define RTC_ALRM_SU(n) ((n) << 0) +/** @} */ + +/* Requires services from the EXTI driver.*/ +#if !defined(STM32_EXTI_REQUIRED) +#define STM32_EXTI_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief RTC PRES register initialization. + * @note The default is calculated for a 32768Hz clock. + */ +#if !defined(STM32_RTC_PRESA_VALUE) || defined(__DOXYGEN__) +#define STM32_RTC_PRESA_VALUE 32 +#endif + +/** + * @brief RTC PRESS divider initialization. + * @note The default is calculated for a 32768Hz clock. + */ +#if !defined(STM32_RTC_PRESS_VALUE) || defined(__DOXYGEN__) +#define STM32_RTC_PRESS_VALUE 1024 +#endif + +/** + * @brief RTC CR register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + */ +#if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__) +#define STM32_RTC_CR_INIT 0 +#endif + +/** + * @brief RTC TAMPCR register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + * @note On some devices this values goes in the similar TAFCR register. + */ +#if !defined(STM32_RTC_TAMPCR_INIT) || defined(__DOXYGEN__) +#define STM32_RTC_TAMPCR_INIT 0 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !STM32_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if defined(STM32_RTC_CK) && !defined(STM32_RTCCLK) +#define STM32_RTCCLK STM32_RTC_CK +#endif + +#if !defined(STM32_RTCCLK) +#error "RTC clock not exported by HAL layer" +#endif + +#if STM32_PCLK1 < (STM32_RTCCLK * 7) +#error "STM32_PCLK1 frequency is too low" +#endif + +/** + * @brief Initialization for the RTC_PRER register. + */ +#define STM32_RTC_PRER_BITS RTC_PRER(STM32_RTC_PRESA_VALUE, \ + STM32_RTC_PRESS_VALUE) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_ALARM_A = 0, /** Alarm A. */ + RTC_EVENT_ALARM_B = 1, /** Alarm B. */ + RTC_EVENT_TS = 2, /** Time stamp. */ + RTC_EVENT_TS_OVF = 3, /** Time stamp overflow. */ + RTC_EVENT_TAMP1 = 4, /** Tamper 1. */ + RTC_EVENT_TAMP2 = 5, /** Tamper 2- */ + RTC_EVENT_TAMP3 = 6, /** Tamper 3. */ + RTC_EVENT_WAKEUP = 7 /** Wakeup. */ + } rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct hal_rtc_alarm { + /** + * @brief Type of an alarm as encoded in RTC ALRMxR registers. + */ + uint32_t alrmr; +} RTCAlarm; + +#if STM32_RTC_HAS_PERIODIC_WAKEUPS +/** + * @brief Type of a wakeup as encoded in RTC WUTR register. + */ +typedef struct hal_rtc_wakeup { + /** + * @brief Wakeup as encoded in RTC WUTR register. + * @note ((WUTR == 0) || (WUCKSEL == 3)) are a forbidden combination. + * @note Bits 16..18 are copied in the CR bits 0..2 (WUCKSEL). + */ + uint32_t wutr; +} RTCWakeup; +#endif + +/** + * @brief Implementation-specific @p RTCDriver fields. + */ +#define rtc_lld_driver_fields \ + /* Pointer to the RTC registers block.*/ \ + RTC_TypeDef *rtc; \ + /* Callback pointer.*/ \ + rtccb_t callback + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); +#if RTC_SUPPORTS_CALLBACKS == TRUE + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); +#endif +#if RTC_ALARMS > 0 + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec); +#endif +#if STM32_RTC_HAS_PERIODIC_WAKEUPS + void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec); + void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec); +#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* HAL_RTC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RTCv3/driver.mk b/os/hal/ports/STM32/LLD/RTCv3/driver.mk index be3a5ad06e..d8b1181017 100644 --- a/os/hal/ports/STM32/LLD/RTCv3/driver.mk +++ b/os/hal/ports/STM32/LLD/RTCv3/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3 diff --git a/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c b/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c index e586c70fe3..4e96d94103 100644 --- a/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c +++ b/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c @@ -1,717 +1,717 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file RTCv3/hal_rtc_lld.c - * @brief STM32 RTC low level driver. - * - * @addtogroup RTC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define RTC_TR_PM_OFFSET RTC_TR_PM_Pos -#define RTC_TR_HT_OFFSET RTC_TR_HT_Pos -#define RTC_TR_HU_OFFSET RTC_TR_HU_Pos -#define RTC_TR_MNT_OFFSET RTC_TR_MNT_Pos -#define RTC_TR_MNU_OFFSET RTC_TR_MNU_Pos -#define RTC_TR_ST_OFFSET RTC_TR_ST_Pos -#define RTC_TR_SU_OFFSET RTC_TR_SU_Pos - -#define RTC_DR_YT_OFFSET RTC_DR_YT_Pos -#define RTC_DR_YU_OFFSET RTC_DR_YU_Pos -#define RTC_DR_WDU_OFFSET RTC_DR_WDU_Pos -#define RTC_DR_MT_OFFSET RTC_DR_MT_Pos -#define RTC_DR_MU_OFFSET RTC_DR_MU_Pos -#define RTC_DR_DT_OFFSET RTC_DR_DT_Pos -#define RTC_DR_DU_OFFSET RTC_DR_DU_Pos - -#define RTC_CR_BKP_OFFSET RTC_CR_BKP_Pos - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief RTC driver identifier. - */ -RTCDriver RTCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Beginning of configuration procedure. - * - * @notapi - */ -static void rtc_enter_init(void) { - - RTCD1.rtc->ICSR |= RTC_ICSR_INIT; - while ((RTCD1.rtc->ICSR & RTC_ICSR_INITF) == 0) - ; -} - -/** - * @brief Finalizing of configuration procedure. - * - * @notapi - */ -static inline void rtc_exit_init(void) { - - RTCD1.rtc->ICSR &= ~RTC_ICSR_INIT; -} - -/** - * @brief Converts time from TR register encoding to timespec. - * - * @param[in] tr TR register value - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -static void rtc_decode_time(uint32_t tr, RTCDateTime *timespec) { - uint32_t n; - - n = ((tr >> RTC_TR_HT_OFFSET) & 3) * 36000000; - n += ((tr >> RTC_TR_HU_OFFSET) & 15) * 3600000; - n += ((tr >> RTC_TR_MNT_OFFSET) & 7) * 600000; - n += ((tr >> RTC_TR_MNU_OFFSET) & 15) * 60000; - n += ((tr >> RTC_TR_ST_OFFSET) & 7) * 10000; - n += ((tr >> RTC_TR_SU_OFFSET) & 15) * 1000; - timespec->millisecond = n; -} - -/** - * @brief Converts date from DR register encoding to timespec. - * - * @param[in] dr DR register value - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -static void rtc_decode_date(uint32_t dr, RTCDateTime *timespec) { - - timespec->year = (((dr >> RTC_DR_YT_OFFSET) & 15) * 10) + - ((dr >> RTC_DR_YU_OFFSET) & 15); - timespec->month = (((dr >> RTC_TR_MNT_OFFSET) & 1) * 10) + - ((dr >> RTC_TR_MNU_OFFSET) & 15); - timespec->day = (((dr >> RTC_DR_DT_OFFSET) & 3) * 10) + - ((dr >> RTC_DR_DU_OFFSET) & 15); - timespec->dayofweek = ((dr >> RTC_DR_WDU_OFFSET) & 7) + 1; -} - -/** - * @brief Converts time from timespec to TR register encoding. - * - * @param[in] timespec pointer to a @p RTCDateTime structure - * @return the TR register encoding. - * - * @notapi - */ -static uint32_t rtc_encode_time(const RTCDateTime *timespec) { - uint32_t n, tr = 0; - - /* Subseconds cannot be set.*/ - n = timespec->millisecond / 1000; - - /* Seconds conversion.*/ - tr = tr | ((n % 10) << RTC_TR_SU_OFFSET); - n /= 10; - tr = tr | ((n % 6) << RTC_TR_ST_OFFSET); - n /= 6; - - /* Minutes conversion.*/ - tr = tr | ((n % 10) << RTC_TR_MNU_OFFSET); - n /= 10; - tr = tr | ((n % 6) << RTC_TR_MNT_OFFSET); - n /= 6; - - /* Hours conversion.*/ - tr = tr | ((n % 10) << RTC_TR_HU_OFFSET); - n /= 10; - tr = tr | (n << RTC_TR_HT_OFFSET); - - return tr; -} - -/** - * @brief Converts a date from timespec to DR register encoding. - * - * @param[in] timespec pointer to a @p RTCDateTime structure - * @return the DR register encoding. - * - * @notapi - */ -static uint32_t rtc_encode_date(const RTCDateTime *timespec) { - uint32_t n, dr = 0; - - /* Year conversion. Note, only years last two digits are considered.*/ - n = timespec->year; - dr = dr | ((n % 10) << RTC_DR_YU_OFFSET); - n /= 10; - dr = dr | ((n % 10) << RTC_DR_YT_OFFSET); - - /* Months conversion.*/ - n = timespec->month; - dr = dr | ((n % 10) << RTC_DR_MU_OFFSET); - n /= 10; - dr = dr | ((n % 10) << RTC_DR_MT_OFFSET); - - /* Days conversion.*/ - n = timespec->day; - dr = dr | ((n % 10) << RTC_DR_DU_OFFSET); - n /= 10; - dr = dr | ((n % 10) << RTC_DR_DT_OFFSET); - - /* Days of week conversion.*/ - dr = dr | ((timespec->dayofweek) << RTC_DR_WDU_OFFSET); - - return dr; -} - -#if RTC_HAS_STORAGE == TRUE -static size_t _getsize(void *instance) { - - (void)instance; - - return (size_t)STM32_RTC_STORAGE_SIZE; -} - -static ps_error_t _read(void *instance, ps_offset_t offset, - size_t n, uint8_t *rp) { - volatile uint32_t *bkpr = &((RTCDriver *)instance)->tamp->BKP0R; - unsigned i; - - osalDbgCheck((instance != NULL) && (rp != NULL)); - osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); - osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && - (offset + n <= STM32_RTC_STORAGE_SIZE)); - - for (i = 0; i < (unsigned)n; i++) { - unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); - unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); - *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U)); - } - - return PS_NO_ERROR; -} - -static ps_error_t _write(void *instance, ps_offset_t offset, - size_t n, const uint8_t *wp) { - volatile uint32_t *bkpr = &((RTCDriver *)instance)->tamp->BKP0R; - unsigned i; - - osalDbgCheck((instance != NULL) && (wp != NULL)); - osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); - osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && - (offset + n <= STM32_RTC_STORAGE_SIZE)); - - for (i = 0; i < (unsigned)n; i++) { - unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); - unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); - uint32_t regval = bkpr[index]; - regval &= ~(0xFFU << (shift * 8U)); - regval |= (uint32_t)*wp++ << (shift * 8U); - bkpr[index] = regval; - } - - return PS_NO_ERROR; -} - -/** - * @brief VMT for the RTC storage file interface. - */ -struct RTCDriverVMT _rtc_lld_vmt = { - (size_t)0, - _getsize, _read, _write -}; -#endif /* RTC_HAS_STORAGE == TRUE */ - -/** - * @brief RTC ISR service routine. - * - */ -static void rtc_lld_serve_interrupt(void) { - - uint32_t isr; - - /* Get and clear the RTC interrupts. */ - isr = RTCD1.rtc->MISR; - RTCD1.rtc->SCR = isr; - - /* Clear EXTI events. */ - STM32_RTC_CLEAR_ALL_EXTI(); - - /* Process call backs if enabled. */ - if (RTCD1.callback != NULL) { - -#if defined(RTC_MISR_WUTMF) - if ((isr & RTC_MISR_WUTMF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP); - } -#endif - -#if defined(RTC_MISR_ALRAMF) - if ((isr & RTC_MISR_ALRAMF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A); - } -#endif -#if defined(RTC_MISR_ALRBMF) - if ((isr & RTC_MISR_ALRBMF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B); - } -#endif -#if defined(RTC_MISR_ITSMF) - if ((isr & RTC_MISR_ITSMF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TS); - } -#endif -#if defined(RTC_MISR_TSOVMF) - if ((isr & RTC_MISR_TSOVMF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF); - } -#endif - - /* Get and clear the TAMP interrupts. */ - isr = RTCD1.tamp->MISR; - RTCD1.tamp->SCR = isr; -#if defined(TAMP_MISR_TAMP1MF) - if ((isr & TAMP_MISR_TAMP1MF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); - } -#endif -#if defined(TAMP_MISR_TAMP2MF) - if ((isr & TAMP_MISR_TAMP2MF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); - } -#endif -#if defined(TAMP_MISR_ITAMP3MF) - if ((isr & TAMP_MISR_ITAMP3MF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3); - } -#endif -#if defined(TAMP_MISR_ITAMP4MF) - if ((isr & TAMP_MISR_ITAMP4MF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP4); - } -#endif -#if defined(TAMP_MISR_ITAMP5MF) - if ((isr & TAMP_MISR_ITAMP5MF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP5); - } -#endif -#if defined(TAMP_MISR_ITAMP6MF) - if ((isr & TAMP_MISR_ITAMP6MF) != 0U) { - RTCD1.callback(&RTCD1, RTC_EVENT_TAMP6); - } -#endif - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if defined(STM32_RTC_COMMON_HANDLER) -#if !defined(STM32_RTC_SUPPRESS_COMMON_ISR) -/** - * @brief RTC common interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_COMMON_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - rtc_lld_serve_interrupt(); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_RTC_SUPPRESS_COMMON_ISR) */ - -#elif defined(STM32_RTC_TAMP_STAMP_HANDLER) && \ - defined(STM32_RTC_WKUP_HANDLER) && \ - defined(STM32_RTC_ALARM_HANDLER) -/** - * @brief RTC TAMP/STAMP interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_TAMP_STAMP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - rtc_lld_serve_interrupt(); - - OSAL_IRQ_EPILOGUE(); -} -/** - * @brief RTC wakeup interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_WKUP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - rtc_lld_serve_interrupt(); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief RTC alarm interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_RTC_ALARM_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - rtc_lld_serve_interrupt(); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "missing required RTC handler definitions in registry" -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enable access to registers. - * - * @notapi - */ -void rtc_lld_init(void) { - - /* RTC object initialization.*/ - rtcObjectInit(&RTCD1); - - /* RTC pointer initialization.*/ - RTCD1.rtc = RTC; - - /* Disable write protection. */ - RTCD1.rtc->WPR = 0xCA; - RTCD1.rtc->WPR = 0x53; - - /* If calendar has not been initialized yet then proceed with the - initial setup.*/ - if (!(RTCD1.rtc->ICSR & RTC_ICSR_INITS)) { - - rtc_enter_init(); - - RTCD1.rtc->CR |= (STM32_RTC_CR_INIT & STM32_RTC_CR_MASK); - /* Setting PRER has to be done as two writes. Write Sync part first - then Sync + Async. */ - RTCD1.rtc->PRER = STM32_RTC_PRER_BITS & 0x7FFF; - RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; - - rtc_exit_init(); - } - else { - RTCD1.rtc->ICSR &= ~RTC_ICSR_RSF; - } - - /* TAMP pointer initialization. */ - RTCD1.tamp = TAMP; - - /* Initialise TAMP registers. */ - RTCD1.tamp->CR1 |= (STM32_TAMP_CR1_INIT & STM32_TAMP_CR1_MASK); - RTCD1.tamp->CR2 |= (STM32_TAMP_CR2_INIT & STM32_TAMP_CR2_MASK); - RTCD1.tamp->FLTCR |= (STM32_TAMP_FLTCR_INIT & STM32_TAMP_FLTCR_MASK); - RTCD1.tamp->IER |= (STM32_TAMP_IER_INIT & STM32_TAMP_IER_MASK); - - /* Callback initially disabled.*/ - RTCD1.callback = NULL; - - /* Enabling RTC-related EXTI lines.*/ - STM32_RTC_ENABLE_ALL_EXTI(); - - /* IRQ vectors permanently assigned to this driver.*/ - STM32_RTC_IRQ_ENABLE(); -} - -/** - * @brief Set current time. - * @note Fractional part will be silently ignored. There is no possibility - * to set it on STM32 platform. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { - uint32_t dr, tr; - syssts_t sts; - - tr = rtc_encode_time(timespec); - dr = rtc_encode_date(timespec); - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - /* Writing the registers.*/ - rtc_enter_init(); - rtcp->rtc->TR = tr; - rtcp->rtc->DR = dr; - rtcp->rtc->CR = (rtcp->rtc->CR & ~(1U << RTC_CR_BKP_OFFSET)) | - (timespec->dstflag << RTC_CR_BKP_OFFSET); - rtc_exit_init(); - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Get current time. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @notapi - */ -void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { - uint32_t dr, tr, cr; - uint32_t subs; -#if STM32_RTC_HAS_SUBSECONDS - uint32_t ssr; -#endif /* STM32_RTC_HAS_SUBSECONDS */ - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - /* Synchronization with the RTC and reading the registers, note - DR must be read last.*/ - while ((rtcp->rtc->ICSR & RTC_ICSR_RSF) == 0) - ; -#if STM32_RTC_HAS_SUBSECONDS - ssr = rtcp->rtc->SSR; -#endif /* STM32_RTC_HAS_SUBSECONDS */ - tr = rtcp->rtc->TR; - dr = rtcp->rtc->DR; - cr = rtcp->rtc->CR; - rtcp->rtc->ICSR &= ~RTC_ICSR_RSF; - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); - - /* Decoding day time, this starts the atomic read sequence, see "Reading - the calendar" in the RTC documentation.*/ - rtc_decode_time(tr, timespec); - - /* If the RTC is capable of sub-second counting then the value is - normalized in milliseconds and added to the time.*/ -#if STM32_RTC_HAS_SUBSECONDS - subs = (((STM32_RTC_PRESS_VALUE - 1U) - ssr) * 1000U) / STM32_RTC_PRESS_VALUE; -#else - subs = 0; -#endif /* STM32_RTC_HAS_SUBSECONDS */ - timespec->millisecond += subs; - - /* Decoding date, this concludes the atomic read sequence.*/ - rtc_decode_date(dr, timespec); - - /* Retrieving the DST bit.*/ - timespec->dstflag = (cr >> RTC_CR_BKP_OFFSET) & 1; -} - -#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) -/** - * @brief Set alarm time. - * @note Default value after BKP domain reset for both comparators is 0. - * @note Function does not performs any checks of alarm time validity. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure. - * @param[in] alarm alarm identifier. Can be 0 or 1. - * @param[in] alarmspec pointer to a @p RTCAlarm structure. - * - * @notapi - */ -void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - if (alarm == 0) { - if (alarmspec != NULL) { - rtcp->rtc->CR &= ~RTC_CR_ALRAE; - while (!(rtcp->rtc->ICSR & RTC_ICSR_ALRAWF)) - ; - rtcp->rtc->ALRMAR = alarmspec->alrmr; - rtcp->rtc->CR |= RTC_CR_ALRAE; - rtcp->rtc->CR |= RTC_CR_ALRAIE; - } - else { - rtcp->rtc->CR &= ~RTC_CR_ALRAIE; - rtcp->rtc->CR &= ~RTC_CR_ALRAE; - } - } -#if RTC_ALARMS > 1 - else { - if (alarmspec != NULL) { - rtcp->rtc->CR &= ~RTC_CR_ALRBE; - while (!(rtcp->rtc->ICSR & RTC_ICSR_ALRBWF)) - ; - rtcp->rtc->ALRMBR = alarmspec->alrmr; - rtcp->rtc->CR |= RTC_CR_ALRBE; - rtcp->rtc->CR |= RTC_CR_ALRBIE; - } - else { - rtcp->rtc->CR &= ~RTC_CR_ALRBIE; - rtcp->rtc->CR &= ~RTC_CR_ALRBE; - } - } -#endif /* RTC_ALARMS > 1 */ - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Get alarm time. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier. Can be 0 or 1. - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ -void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec) { - - if (alarm == 0) - alarmspec->alrmr = rtcp->rtc->ALRMAR; -#if RTC_ALARMS > 1 - else - alarmspec->alrmr = rtcp->rtc->ALRMBR; -#endif /* RTC_ALARMS > 1 */ -} -#endif /* RTC_ALARMS > 0 */ - -/** - * @brief Enables or disables RTC callbacks. - * @details This function enables or disables callbacks, use a @p NULL pointer - * in order to disable a callback. - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL - * - * @notapi - */ -void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { - - rtcp->callback = callback; -} - -#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__) -/** - * @brief Sets time of periodic wakeup. - * @note Default value after BKP domain reset is 0x0000FFFF - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] wakeupspec pointer to a @p RTCWakeup structure - * - * @api - */ -void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - if (wakeupspec != NULL) { - osalDbgCheck(wakeupspec->wutr != 0x30000); - - rtcp->rtc->CR &= ~RTC_CR_WUTE; - rtcp->rtc->CR &= ~RTC_CR_WUTIE; - while (!(rtcp->rtc->ICSR & RTC_ICSR_WUTWF)) - ; - rtcp->rtc->WUTR = wakeupspec->wutr & 0xFFFF; - rtcp->rtc->CR &= ~RTC_CR_WUCKSEL; - rtcp->rtc->CR |= (wakeupspec->wutr >> 16) & RTC_CR_WUCKSEL; - rtcp->rtc->CR |= RTC_CR_WUTIE; - rtcp->rtc->CR |= RTC_CR_WUTE; - } - else { - rtcp->rtc->CR &= ~RTC_CR_WUTE; - rtcp->rtc->CR &= ~RTC_CR_WUTIE; - } - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} - -/** - * @brief Gets time of periodic wakeup. - * @note Default value after BKP domain reset is 0x0000FFFF - * @note The function can be called from any context. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] wakeupspec pointer to a @p RTCWakeup structure - * - * @api - */ -void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) { - syssts_t sts; - - /* Entering a reentrant critical zone.*/ - sts = osalSysGetStatusAndLockX(); - - wakeupspec->wutr = 0; - wakeupspec->wutr |= rtcp->rtc->WUTR; - wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16; - - /* Leaving a reentrant critical zone.*/ - osalSysRestoreStatusX(sts); -} -#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ - -#endif /* HAL_USE_RTC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv3/hal_rtc_lld.c + * @brief STM32 RTC low level driver. + * + * @addtogroup RTC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define RTC_TR_PM_OFFSET RTC_TR_PM_Pos +#define RTC_TR_HT_OFFSET RTC_TR_HT_Pos +#define RTC_TR_HU_OFFSET RTC_TR_HU_Pos +#define RTC_TR_MNT_OFFSET RTC_TR_MNT_Pos +#define RTC_TR_MNU_OFFSET RTC_TR_MNU_Pos +#define RTC_TR_ST_OFFSET RTC_TR_ST_Pos +#define RTC_TR_SU_OFFSET RTC_TR_SU_Pos + +#define RTC_DR_YT_OFFSET RTC_DR_YT_Pos +#define RTC_DR_YU_OFFSET RTC_DR_YU_Pos +#define RTC_DR_WDU_OFFSET RTC_DR_WDU_Pos +#define RTC_DR_MT_OFFSET RTC_DR_MT_Pos +#define RTC_DR_MU_OFFSET RTC_DR_MU_Pos +#define RTC_DR_DT_OFFSET RTC_DR_DT_Pos +#define RTC_DR_DU_OFFSET RTC_DR_DU_Pos + +#define RTC_CR_BKP_OFFSET RTC_CR_BKP_Pos + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Beginning of configuration procedure. + * + * @notapi + */ +static void rtc_enter_init(void) { + + RTCD1.rtc->ICSR |= RTC_ICSR_INIT; + while ((RTCD1.rtc->ICSR & RTC_ICSR_INITF) == 0) + ; +} + +/** + * @brief Finalizing of configuration procedure. + * + * @notapi + */ +static inline void rtc_exit_init(void) { + + RTCD1.rtc->ICSR &= ~RTC_ICSR_INIT; +} + +/** + * @brief Converts time from TR register encoding to timespec. + * + * @param[in] tr TR register value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +static void rtc_decode_time(uint32_t tr, RTCDateTime *timespec) { + uint32_t n; + + n = ((tr >> RTC_TR_HT_OFFSET) & 3) * 36000000; + n += ((tr >> RTC_TR_HU_OFFSET) & 15) * 3600000; + n += ((tr >> RTC_TR_MNT_OFFSET) & 7) * 600000; + n += ((tr >> RTC_TR_MNU_OFFSET) & 15) * 60000; + n += ((tr >> RTC_TR_ST_OFFSET) & 7) * 10000; + n += ((tr >> RTC_TR_SU_OFFSET) & 15) * 1000; + timespec->millisecond = n; +} + +/** + * @brief Converts date from DR register encoding to timespec. + * + * @param[in] dr DR register value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +static void rtc_decode_date(uint32_t dr, RTCDateTime *timespec) { + + timespec->year = (((dr >> RTC_DR_YT_OFFSET) & 15) * 10) + + ((dr >> RTC_DR_YU_OFFSET) & 15); + timespec->month = (((dr >> RTC_TR_MNT_OFFSET) & 1) * 10) + + ((dr >> RTC_TR_MNU_OFFSET) & 15); + timespec->day = (((dr >> RTC_DR_DT_OFFSET) & 3) * 10) + + ((dr >> RTC_DR_DU_OFFSET) & 15); + timespec->dayofweek = ((dr >> RTC_DR_WDU_OFFSET) & 7) + 1; +} + +/** + * @brief Converts time from timespec to TR register encoding. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @return the TR register encoding. + * + * @notapi + */ +static uint32_t rtc_encode_time(const RTCDateTime *timespec) { + uint32_t n, tr = 0; + + /* Subseconds cannot be set.*/ + n = timespec->millisecond / 1000; + + /* Seconds conversion.*/ + tr = tr | ((n % 10) << RTC_TR_SU_OFFSET); + n /= 10; + tr = tr | ((n % 6) << RTC_TR_ST_OFFSET); + n /= 6; + + /* Minutes conversion.*/ + tr = tr | ((n % 10) << RTC_TR_MNU_OFFSET); + n /= 10; + tr = tr | ((n % 6) << RTC_TR_MNT_OFFSET); + n /= 6; + + /* Hours conversion.*/ + tr = tr | ((n % 10) << RTC_TR_HU_OFFSET); + n /= 10; + tr = tr | (n << RTC_TR_HT_OFFSET); + + return tr; +} + +/** + * @brief Converts a date from timespec to DR register encoding. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @return the DR register encoding. + * + * @notapi + */ +static uint32_t rtc_encode_date(const RTCDateTime *timespec) { + uint32_t n, dr = 0; + + /* Year conversion. Note, only years last two digits are considered.*/ + n = timespec->year; + dr = dr | ((n % 10) << RTC_DR_YU_OFFSET); + n /= 10; + dr = dr | ((n % 10) << RTC_DR_YT_OFFSET); + + /* Months conversion.*/ + n = timespec->month; + dr = dr | ((n % 10) << RTC_DR_MU_OFFSET); + n /= 10; + dr = dr | ((n % 10) << RTC_DR_MT_OFFSET); + + /* Days conversion.*/ + n = timespec->day; + dr = dr | ((n % 10) << RTC_DR_DU_OFFSET); + n /= 10; + dr = dr | ((n % 10) << RTC_DR_DT_OFFSET); + + /* Days of week conversion.*/ + dr = dr | ((timespec->dayofweek) << RTC_DR_WDU_OFFSET); + + return dr; +} + +#if RTC_HAS_STORAGE == TRUE +static size_t _getsize(void *instance) { + + (void)instance; + + return (size_t)STM32_RTC_STORAGE_SIZE; +} + +static ps_error_t _read(void *instance, ps_offset_t offset, + size_t n, uint8_t *rp) { + volatile uint32_t *bkpr = &((RTCDriver *)instance)->tamp->BKP0R; + unsigned i; + + osalDbgCheck((instance != NULL) && (rp != NULL)); + osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); + osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && + (offset + n <= STM32_RTC_STORAGE_SIZE)); + + for (i = 0; i < (unsigned)n; i++) { + unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); + unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); + *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U)); + } + + return PS_NO_ERROR; +} + +static ps_error_t _write(void *instance, ps_offset_t offset, + size_t n, const uint8_t *wp) { + volatile uint32_t *bkpr = &((RTCDriver *)instance)->tamp->BKP0R; + unsigned i; + + osalDbgCheck((instance != NULL) && (wp != NULL)); + osalDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); + osalDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && + (offset + n <= STM32_RTC_STORAGE_SIZE)); + + for (i = 0; i < (unsigned)n; i++) { + unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); + unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); + uint32_t regval = bkpr[index]; + regval &= ~(0xFFU << (shift * 8U)); + regval |= (uint32_t)*wp++ << (shift * 8U); + bkpr[index] = regval; + } + + return PS_NO_ERROR; +} + +/** + * @brief VMT for the RTC storage file interface. + */ +struct RTCDriverVMT _rtc_lld_vmt = { + (size_t)0, + _getsize, _read, _write +}; +#endif /* RTC_HAS_STORAGE == TRUE */ + +/** + * @brief RTC ISR service routine. + * + */ +static void rtc_lld_serve_interrupt(void) { + + uint32_t isr; + + /* Get and clear the RTC interrupts. */ + isr = RTCD1.rtc->MISR; + RTCD1.rtc->SCR = isr; + + /* Clear EXTI events. */ + STM32_RTC_CLEAR_ALL_EXTI(); + + /* Process call backs if enabled. */ + if (RTCD1.callback != NULL) { + +#if defined(RTC_MISR_WUTMF) + if ((isr & RTC_MISR_WUTMF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP); + } +#endif + +#if defined(RTC_MISR_ALRAMF) + if ((isr & RTC_MISR_ALRAMF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A); + } +#endif +#if defined(RTC_MISR_ALRBMF) + if ((isr & RTC_MISR_ALRBMF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B); + } +#endif +#if defined(RTC_MISR_ITSMF) + if ((isr & RTC_MISR_ITSMF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TS); + } +#endif +#if defined(RTC_MISR_TSOVMF) + if ((isr & RTC_MISR_TSOVMF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF); + } +#endif + + /* Get and clear the TAMP interrupts. */ + isr = RTCD1.tamp->MISR; + RTCD1.tamp->SCR = isr; +#if defined(TAMP_MISR_TAMP1MF) + if ((isr & TAMP_MISR_TAMP1MF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1); + } +#endif +#if defined(TAMP_MISR_TAMP2MF) + if ((isr & TAMP_MISR_TAMP2MF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2); + } +#endif +#if defined(TAMP_MISR_ITAMP3MF) + if ((isr & TAMP_MISR_ITAMP3MF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3); + } +#endif +#if defined(TAMP_MISR_ITAMP4MF) + if ((isr & TAMP_MISR_ITAMP4MF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP4); + } +#endif +#if defined(TAMP_MISR_ITAMP5MF) + if ((isr & TAMP_MISR_ITAMP5MF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP5); + } +#endif +#if defined(TAMP_MISR_ITAMP6MF) + if ((isr & TAMP_MISR_ITAMP6MF) != 0U) { + RTCD1.callback(&RTCD1, RTC_EVENT_TAMP6); + } +#endif + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if defined(STM32_RTC_COMMON_HANDLER) +#if !defined(STM32_RTC_SUPPRESS_COMMON_ISR) +/** + * @brief RTC common interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_COMMON_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + rtc_lld_serve_interrupt(); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_RTC_SUPPRESS_COMMON_ISR) */ + +#elif defined(STM32_RTC_TAMP_STAMP_HANDLER) && \ + defined(STM32_RTC_WKUP_HANDLER) && \ + defined(STM32_RTC_ALARM_HANDLER) +/** + * @brief RTC TAMP/STAMP interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_TAMP_STAMP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + rtc_lld_serve_interrupt(); + + OSAL_IRQ_EPILOGUE(); +} +/** + * @brief RTC wakeup interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_WKUP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + rtc_lld_serve_interrupt(); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief RTC alarm interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_RTC_ALARM_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + rtc_lld_serve_interrupt(); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "missing required RTC handler definitions in registry" +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enable access to registers. + * + * @notapi + */ +void rtc_lld_init(void) { + + /* RTC object initialization.*/ + rtcObjectInit(&RTCD1); + + /* RTC pointer initialization.*/ + RTCD1.rtc = RTC; + + /* Disable write protection. */ + RTCD1.rtc->WPR = 0xCA; + RTCD1.rtc->WPR = 0x53; + + /* If calendar has not been initialized yet then proceed with the + initial setup.*/ + if (!(RTCD1.rtc->ICSR & RTC_ICSR_INITS)) { + + rtc_enter_init(); + + RTCD1.rtc->CR |= (STM32_RTC_CR_INIT & STM32_RTC_CR_MASK); + /* Setting PRER has to be done as two writes. Write Sync part first + then Sync + Async. */ + RTCD1.rtc->PRER = STM32_RTC_PRER_BITS & 0x7FFF; + RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; + + rtc_exit_init(); + } + else { + RTCD1.rtc->ICSR &= ~RTC_ICSR_RSF; + } + + /* TAMP pointer initialization. */ + RTCD1.tamp = TAMP; + + /* Initialise TAMP registers. */ + RTCD1.tamp->CR1 |= (STM32_TAMP_CR1_INIT & STM32_TAMP_CR1_MASK); + RTCD1.tamp->CR2 |= (STM32_TAMP_CR2_INIT & STM32_TAMP_CR2_MASK); + RTCD1.tamp->FLTCR |= (STM32_TAMP_FLTCR_INIT & STM32_TAMP_FLTCR_MASK); + RTCD1.tamp->IER |= (STM32_TAMP_IER_INIT & STM32_TAMP_IER_MASK); + + /* Callback initially disabled.*/ + RTCD1.callback = NULL; + + /* Enabling RTC-related EXTI lines.*/ + STM32_RTC_ENABLE_ALL_EXTI(); + + /* IRQ vectors permanently assigned to this driver.*/ + STM32_RTC_IRQ_ENABLE(); +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to set it on STM32 platform. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { + uint32_t dr, tr; + syssts_t sts; + + tr = rtc_encode_time(timespec); + dr = rtc_encode_date(timespec); + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + /* Writing the registers.*/ + rtc_enter_init(); + rtcp->rtc->TR = tr; + rtcp->rtc->DR = dr; + rtcp->rtc->CR = (rtcp->rtc->CR & ~(1U << RTC_CR_BKP_OFFSET)) | + (timespec->dstflag << RTC_CR_BKP_OFFSET); + rtc_exit_init(); + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Get current time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { + uint32_t dr, tr, cr; + uint32_t subs; +#if STM32_RTC_HAS_SUBSECONDS + uint32_t ssr; +#endif /* STM32_RTC_HAS_SUBSECONDS */ + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + /* Synchronization with the RTC and reading the registers, note + DR must be read last.*/ + while ((rtcp->rtc->ICSR & RTC_ICSR_RSF) == 0) + ; +#if STM32_RTC_HAS_SUBSECONDS + ssr = rtcp->rtc->SSR; +#endif /* STM32_RTC_HAS_SUBSECONDS */ + tr = rtcp->rtc->TR; + dr = rtcp->rtc->DR; + cr = rtcp->rtc->CR; + rtcp->rtc->ICSR &= ~RTC_ICSR_RSF; + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); + + /* Decoding day time, this starts the atomic read sequence, see "Reading + the calendar" in the RTC documentation.*/ + rtc_decode_time(tr, timespec); + + /* If the RTC is capable of sub-second counting then the value is + normalized in milliseconds and added to the time.*/ +#if STM32_RTC_HAS_SUBSECONDS + subs = (((STM32_RTC_PRESS_VALUE - 1U) - ssr) * 1000U) / STM32_RTC_PRESS_VALUE; +#else + subs = 0; +#endif /* STM32_RTC_HAS_SUBSECONDS */ + timespec->millisecond += subs; + + /* Decoding date, this concludes the atomic read sequence.*/ + rtc_decode_date(dr, timespec); + + /* Retrieving the DST bit.*/ + timespec->dstflag = (cr >> RTC_CR_BKP_OFFSET) & 1; +} + +#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) +/** + * @brief Set alarm time. + * @note Default value after BKP domain reset for both comparators is 0. + * @note Function does not performs any checks of alarm time validity. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure. + * @param[in] alarm alarm identifier. Can be 0 or 1. + * @param[in] alarmspec pointer to a @p RTCAlarm structure. + * + * @notapi + */ +void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + if (alarm == 0) { + if (alarmspec != NULL) { + rtcp->rtc->CR &= ~RTC_CR_ALRAE; + while (!(rtcp->rtc->ICSR & RTC_ICSR_ALRAWF)) + ; + rtcp->rtc->ALRMAR = alarmspec->alrmr; + rtcp->rtc->CR |= RTC_CR_ALRAE; + rtcp->rtc->CR |= RTC_CR_ALRAIE; + } + else { + rtcp->rtc->CR &= ~RTC_CR_ALRAIE; + rtcp->rtc->CR &= ~RTC_CR_ALRAE; + } + } +#if RTC_ALARMS > 1 + else { + if (alarmspec != NULL) { + rtcp->rtc->CR &= ~RTC_CR_ALRBE; + while (!(rtcp->rtc->ICSR & RTC_ICSR_ALRBWF)) + ; + rtcp->rtc->ALRMBR = alarmspec->alrmr; + rtcp->rtc->CR |= RTC_CR_ALRBE; + rtcp->rtc->CR |= RTC_CR_ALRBIE; + } + else { + rtcp->rtc->CR &= ~RTC_CR_ALRBIE; + rtcp->rtc->CR &= ~RTC_CR_ALRBE; + } + } +#endif /* RTC_ALARMS > 1 */ + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Get alarm time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier. Can be 0 or 1. + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + + if (alarm == 0) + alarmspec->alrmr = rtcp->rtc->ALRMAR; +#if RTC_ALARMS > 1 + else + alarmspec->alrmr = rtcp->rtc->ALRMBR; +#endif /* RTC_ALARMS > 1 */ +} +#endif /* RTC_ALARMS > 0 */ + +/** + * @brief Enables or disables RTC callbacks. + * @details This function enables or disables callbacks, use a @p NULL pointer + * in order to disable a callback. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] callback callback function pointer or @p NULL + * + * @notapi + */ +void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { + + rtcp->callback = callback; +} + +#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__) +/** + * @brief Sets time of periodic wakeup. + * @note Default value after BKP domain reset is 0x0000FFFF + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] wakeupspec pointer to a @p RTCWakeup structure + * + * @api + */ +void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + if (wakeupspec != NULL) { + osalDbgCheck(wakeupspec->wutr != 0x30000); + + rtcp->rtc->CR &= ~RTC_CR_WUTE; + rtcp->rtc->CR &= ~RTC_CR_WUTIE; + while (!(rtcp->rtc->ICSR & RTC_ICSR_WUTWF)) + ; + rtcp->rtc->WUTR = wakeupspec->wutr & 0xFFFF; + rtcp->rtc->CR &= ~RTC_CR_WUCKSEL; + rtcp->rtc->CR |= (wakeupspec->wutr >> 16) & RTC_CR_WUCKSEL; + rtcp->rtc->CR |= RTC_CR_WUTIE; + rtcp->rtc->CR |= RTC_CR_WUTE; + } + else { + rtcp->rtc->CR &= ~RTC_CR_WUTE; + rtcp->rtc->CR &= ~RTC_CR_WUTIE; + } + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Gets time of periodic wakeup. + * @note Default value after BKP domain reset is 0x0000FFFF + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] wakeupspec pointer to a @p RTCWakeup structure + * + * @api + */ +void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) { + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + wakeupspec->wutr = 0; + wakeupspec->wutr |= rtcp->rtc->WUTR; + wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16; + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} +#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ + +#endif /* HAL_USE_RTC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h b/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h index 4097a62505..ab32b9ad17 100644 --- a/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h +++ b/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h @@ -1,289 +1,289 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file RTCv3/hal_rtc_lld.h - * @brief STM32 RTC low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#ifndef HAL_RTC_LLD_H -#define HAL_RTC_LLD_H - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Implementation capabilities - */ -/** - * @brief Callback support int the driver. - */ -#define RTC_SUPPORTS_CALLBACKS TRUE - -/** - * @brief Number of alarms available. - */ -#define RTC_ALARMS STM32_RTC_NUM_ALARMS - -/** - * @brief Presence of a local persistent storage. - */ -#define RTC_HAS_STORAGE (STM32_RTC_STORAGE_SIZE > 0) -/** @} */ - -/** - * @brief RTC PRER register initializer. - */ -#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1)) - -/** - * @name Alarm helper macros - * @{ - */ -#define RTC_ALRM_MSK4 (1U << 31) -#define RTC_ALRM_WDSEL (1U << 30) -#define RTC_ALRM_DT(n) ((n) << 28) -#define RTC_ALRM_DU(n) ((n) << 24) -#define RTC_ALRM_MSK3 (1U << 23) -#define RTC_ALRM_HT(n) ((n) << 20) -#define RTC_ALRM_HU(n) ((n) << 16) -#define RTC_ALRM_MSK2 (1U << 15) -#define RTC_ALRM_MNT(n) ((n) << 12) -#define RTC_ALRM_MNU(n) ((n) << 8) -#define RTC_ALRM_MSK1 (1U << 7) -#define RTC_ALRM_ST(n) ((n) << 4) -#define RTC_ALRM_SU(n) ((n) << 0) -/** @} */ - -/* Requires services from the EXTI driver.*/ -#if !defined(STM32_EXTI_REQUIRED) -#define STM32_EXTI_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief RTC PRESA register initialization. - * @note The default is calculated for a 32768Hz clock. - */ -#if !defined(STM32_RTC_PRESA_VALUE) || defined(__DOXYGEN__) -#define STM32_RTC_PRESA_VALUE 32 -#endif - -/** - * @brief RTC PRESS divider initialization. - * @note The default is calculated for a 32768Hz clock. - */ -#if !defined(STM32_RTC_PRESS_VALUE) || defined(__DOXYGEN__) -#define STM32_RTC_PRESS_VALUE 1024 -#endif - -/** - * @brief RTC CR register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - */ -#if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__) -#define STM32_RTC_CR_INIT 0 -#endif - -/** - * @brief TAMP register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - * @note On some devices this values goes in the similar TAFCR register. - */ -#if !defined(STM32_TAMP_CR1_INIT) || defined(__DOXYGEN__) -#define STM32_TAMP_CR1_INIT 0 -#endif - -/** - * @brief TAMP register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - * @note On some devices this values goes in the similar TAFCR register. - */ -#if !defined(STM32_TAMP_CR2_INIT) || defined(__DOXYGEN__) -#define STM32_TAMP_CR2_INIT 0 -#endif - -/** - * @brief TAMP register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - * @note On some devices this values goes in the similar TAFCR register. - */ -#if !defined(STM32_TAMP_FLTCR_INIT) || defined(__DOXYGEN__) -#define STM32_TAMP_FLTCR_INIT 0 -#endif - -/** - * @brief TAMP register initialization value. - * @note Use this value to initialize features not directly handled by - * the RTC driver. - * @note On some devices this values goes in the similar TAFCR register. - */ -#if !defined(STM32_TAMP_IER_INIT) || defined(__DOXYGEN__) -#define STM32_TAMP_IER_INIT 0 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if HAL_USE_RTC && !STM32_HAS_RTC -#error "RTC not present in the selected device" -#endif - -#if defined(STM32_RTC_CK) && !defined(STM32_RTCCLK) -#define STM32_RTCCLK STM32_RTC_CK -#endif - -#if !defined(STM32_RTCCLK) -#error "RTC clock not exported by HAL layer" -#endif - -#if STM32_RTCCLK == 0 -#error "RTC has no clock source selected" -#endif - -#if STM32_PCLK1 < (STM32_RTCCLK * 7) -#error "STM32_PCLK1 frequency is too low for RTC" -#endif - -/** - * @brief Initialization for the RTC_PRER register. - */ -#define STM32_RTC_PRER_BITS RTC_PRER(STM32_RTC_PRESA_VALUE, \ - STM32_RTC_PRESS_VALUE) - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an RTC event. - */ -typedef enum { - RTC_EVENT_ALARM_A = 0, /** Alarm A. */ - RTC_EVENT_ALARM_B = 1, /** Alarm B. */ - RTC_EVENT_TS = 2, /** Time stamp. */ - RTC_EVENT_TS_OVF = 3, /** Time stamp overflow. */ - RTC_EVENT_TAMP1 = 4, /** Tamper 1. */ - RTC_EVENT_TAMP2 = 5, /** Tamper 2- */ - RTC_EVENT_TAMP3 = 6, /** Tamper 3. */ - RTC_EVENT_TAMP4 = 7, /** Tamper 4. */ - RTC_EVENT_TAMP5 = 8, /** Tamper 5. */ - RTC_EVENT_TAMP6 = 9, /** Tamper 6. */ - RTC_EVENT_WAKEUP = 10, /** Wakeup. */ - } rtcevent_t; - -/** - * @brief Type of a generic RTC callback. - */ -typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); - -/** - * @brief Type of a structure representing an RTC alarm time stamp. - */ -typedef struct hal_rtc_alarm { - /** - * @brief Type of an alarm as encoded in RTC ALRMxR registers. - */ - uint32_t alrmr; -} RTCAlarm; - -#if STM32_RTC_HAS_PERIODIC_WAKEUPS -/** - * @brief Type of a wakeup as encoded in RTC WUTR register. - */ -typedef struct hal_rtc_wakeup { - /** - * @brief Wakeup as encoded in RTC WUTR register. - * @note ((WUTR == 0) || (WUCKSEL == 3)) are a forbidden combination. - * @note Bits 16..18 are copied in the CR bits 0..2 (WUCKSEL). - */ - uint32_t wutr; -} RTCWakeup; -#endif - -/** - * @brief Implementation-specific @p RTCDriver fields. - */ -#define rtc_lld_driver_fields \ - /* Pointer to the RTC registers block.*/ \ - RTC_TypeDef *rtc; \ - /* RTC event callback pointer.*/ \ - rtccb_t callback; \ - /* Pointer to TAMPER registers block. */ \ - TAMP_TypeDef *tamp - - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void rtc_lld_init(void); - void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); - void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); -#if RTC_SUPPORTS_CALLBACKS == TRUE - void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); -#endif -#if RTC_ALARMS > 0 - void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec); - void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec); -#endif -#if STM32_RTC_HAS_PERIODIC_WAKEUPS - void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec); - void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec); -#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_RTC */ - -#endif /* HAL_RTC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv3/hal_rtc_lld.h + * @brief STM32 RTC low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef HAL_RTC_LLD_H +#define HAL_RTC_LLD_H + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Implementation capabilities + */ +/** + * @brief Callback support int the driver. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief Number of alarms available. + */ +#define RTC_ALARMS STM32_RTC_NUM_ALARMS + +/** + * @brief Presence of a local persistent storage. + */ +#define RTC_HAS_STORAGE (STM32_RTC_STORAGE_SIZE > 0) +/** @} */ + +/** + * @brief RTC PRER register initializer. + */ +#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1)) + +/** + * @name Alarm helper macros + * @{ + */ +#define RTC_ALRM_MSK4 (1U << 31) +#define RTC_ALRM_WDSEL (1U << 30) +#define RTC_ALRM_DT(n) ((n) << 28) +#define RTC_ALRM_DU(n) ((n) << 24) +#define RTC_ALRM_MSK3 (1U << 23) +#define RTC_ALRM_HT(n) ((n) << 20) +#define RTC_ALRM_HU(n) ((n) << 16) +#define RTC_ALRM_MSK2 (1U << 15) +#define RTC_ALRM_MNT(n) ((n) << 12) +#define RTC_ALRM_MNU(n) ((n) << 8) +#define RTC_ALRM_MSK1 (1U << 7) +#define RTC_ALRM_ST(n) ((n) << 4) +#define RTC_ALRM_SU(n) ((n) << 0) +/** @} */ + +/* Requires services from the EXTI driver.*/ +#if !defined(STM32_EXTI_REQUIRED) +#define STM32_EXTI_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief RTC PRESA register initialization. + * @note The default is calculated for a 32768Hz clock. + */ +#if !defined(STM32_RTC_PRESA_VALUE) || defined(__DOXYGEN__) +#define STM32_RTC_PRESA_VALUE 32 +#endif + +/** + * @brief RTC PRESS divider initialization. + * @note The default is calculated for a 32768Hz clock. + */ +#if !defined(STM32_RTC_PRESS_VALUE) || defined(__DOXYGEN__) +#define STM32_RTC_PRESS_VALUE 1024 +#endif + +/** + * @brief RTC CR register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + */ +#if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__) +#define STM32_RTC_CR_INIT 0 +#endif + +/** + * @brief TAMP register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + * @note On some devices this values goes in the similar TAFCR register. + */ +#if !defined(STM32_TAMP_CR1_INIT) || defined(__DOXYGEN__) +#define STM32_TAMP_CR1_INIT 0 +#endif + +/** + * @brief TAMP register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + * @note On some devices this values goes in the similar TAFCR register. + */ +#if !defined(STM32_TAMP_CR2_INIT) || defined(__DOXYGEN__) +#define STM32_TAMP_CR2_INIT 0 +#endif + +/** + * @brief TAMP register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + * @note On some devices this values goes in the similar TAFCR register. + */ +#if !defined(STM32_TAMP_FLTCR_INIT) || defined(__DOXYGEN__) +#define STM32_TAMP_FLTCR_INIT 0 +#endif + +/** + * @brief TAMP register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + * @note On some devices this values goes in the similar TAFCR register. + */ +#if !defined(STM32_TAMP_IER_INIT) || defined(__DOXYGEN__) +#define STM32_TAMP_IER_INIT 0 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !STM32_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if defined(STM32_RTC_CK) && !defined(STM32_RTCCLK) +#define STM32_RTCCLK STM32_RTC_CK +#endif + +#if !defined(STM32_RTCCLK) +#error "RTC clock not exported by HAL layer" +#endif + +#if STM32_RTCCLK == 0 +#error "RTC has no clock source selected" +#endif + +#if STM32_PCLK1 < (STM32_RTCCLK * 7) +#error "STM32_PCLK1 frequency is too low for RTC" +#endif + +/** + * @brief Initialization for the RTC_PRER register. + */ +#define STM32_RTC_PRER_BITS RTC_PRER(STM32_RTC_PRESA_VALUE, \ + STM32_RTC_PRESS_VALUE) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_ALARM_A = 0, /** Alarm A. */ + RTC_EVENT_ALARM_B = 1, /** Alarm B. */ + RTC_EVENT_TS = 2, /** Time stamp. */ + RTC_EVENT_TS_OVF = 3, /** Time stamp overflow. */ + RTC_EVENT_TAMP1 = 4, /** Tamper 1. */ + RTC_EVENT_TAMP2 = 5, /** Tamper 2- */ + RTC_EVENT_TAMP3 = 6, /** Tamper 3. */ + RTC_EVENT_TAMP4 = 7, /** Tamper 4. */ + RTC_EVENT_TAMP5 = 8, /** Tamper 5. */ + RTC_EVENT_TAMP6 = 9, /** Tamper 6. */ + RTC_EVENT_WAKEUP = 10, /** Wakeup. */ + } rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct hal_rtc_alarm { + /** + * @brief Type of an alarm as encoded in RTC ALRMxR registers. + */ + uint32_t alrmr; +} RTCAlarm; + +#if STM32_RTC_HAS_PERIODIC_WAKEUPS +/** + * @brief Type of a wakeup as encoded in RTC WUTR register. + */ +typedef struct hal_rtc_wakeup { + /** + * @brief Wakeup as encoded in RTC WUTR register. + * @note ((WUTR == 0) || (WUCKSEL == 3)) are a forbidden combination. + * @note Bits 16..18 are copied in the CR bits 0..2 (WUCKSEL). + */ + uint32_t wutr; +} RTCWakeup; +#endif + +/** + * @brief Implementation-specific @p RTCDriver fields. + */ +#define rtc_lld_driver_fields \ + /* Pointer to the RTC registers block.*/ \ + RTC_TypeDef *rtc; \ + /* RTC event callback pointer.*/ \ + rtccb_t callback; \ + /* Pointer to TAMPER registers block. */ \ + TAMP_TypeDef *tamp + + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); +#if RTC_SUPPORTS_CALLBACKS == TRUE + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); +#endif +#if RTC_ALARMS > 0 + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec); +#endif +#if STM32_RTC_HAS_PERIODIC_WAKEUPS + void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec); + void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec); +#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* HAL_RTC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SDIOv1/driver.mk b/os/hal/ports/STM32/LLD/SDIOv1/driver.mk index a1ce6d48ce..1a1a4bde73 100644 --- a/os/hal/ports/STM32/LLD/SDIOv1/driver.mk +++ b/os/hal/ports/STM32/LLD/SDIOv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1 diff --git a/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c b/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c index 37d4989626..be97134b9a 100644 --- a/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c +++ b/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c @@ -1,876 +1,876 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SDIOv1/hal_sdc_lld.c - * @brief STM32 SDC subsystem low level driver source. - * - * @addtogroup SDC - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SDC_SDIO_DMA_STREAM, \ - STM32_SDC_SDIO_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SDCD1 driver identifier.*/ -SDCDriver SDCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -#if STM32_SDC_SDIO_UNALIGNED_SUPPORT -/** - * @brief Buffer for temporary storage during unaligned transfers. - */ -static union { - uint32_t alignment; - uint8_t buf[MMCSD_BLOCK_SIZE]; -} u; -#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - -/** - * @brief SDIO default configuration. - */ -static const SDCConfig sdc_default_cfg = { - SDC_MODE_4BIT -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Prepares to handle read transaction. - * @details Designed for read special registers from card. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] buf pointer to the read buffer - * @param[in] bytes number of bytes to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp, - uint8_t *buf, uint32_t bytes) { - osalDbgCheck(bytes < 0x1000000); - - sdcp->sdio->DTIMER = STM32_SDC_READ_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, bytes / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; - sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | - SDIO_MASK_DTIMEOUTIE | - SDIO_MASK_STBITERRIE | - SDIO_MASK_RXOVERRIE | - SDIO_MASK_DATAENDIE; - sdcp->sdio->DLEN = bytes; - - /* Transaction starts just after DTEN bit setting.*/ - sdcp->sdio->DCTRL = SDIO_DCTRL_DTDIR | - SDIO_DCTRL_DTMODE | /* Multibyte data transfer.*/ - SDIO_DCTRL_DMAEN | - SDIO_DCTRL_DTEN; - - return HAL_SUCCESS; -} - -/** - * @brief Prepares card to handle read transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to read - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Send read multiple blocks command to card.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - else { - /* Send read single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Prepares card to handle write transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to write - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Write multiple blocks command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - else { - /* Write single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Wait end of data transaction and performs finalizations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - */ -static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, - uint32_t *resp) { - - /* Note the mask is checked before going to sleep because the interrupt - may have occurred before reaching the critical zone.*/ - osalSysLock(); - if (sdcp->sdio->MASK != 0) - osalThreadSuspendS(&sdcp->thread); - if ((sdcp->sdio->STA & SDIO_STA_DATAEND) == 0) { - osalSysUnlock(); - return HAL_FAILED; - } - -#if (defined(STM32F4XX) || defined(STM32F2XX)) - /* Wait until DMA channel enabled to be sure that all data transferred.*/ - while (sdcp->dma->stream->CR & STM32_DMA_CR_EN) - ; - - /* DMA event flags must be manually cleared.*/ - dmaStreamClearInterrupt(sdcp->dma); - - sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; - sdcp->sdio->DCTRL = 0; - osalSysUnlock(); -#else - /* Waits for transfer completion at DMA level, then the stream is - disabled and cleared.*/ - dmaWaitCompletion(sdcp->dma); - - sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; - sdcp->sdio->DCTRL = 0; - osalSysUnlock(); -#endif - - /* Finalize transaction.*/ - if (n > 1) - return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); - - return HAL_SUCCESS; -} - -/** - * @brief Gets SDC errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] sta value of the STA register - * - * @notapi - */ -static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { - uint32_t errors = SDC_NO_ERROR; - - if (sta & SDIO_STA_CCRCFAIL) - errors |= SDC_CMD_CRC_ERROR; - if (sta & SDIO_STA_DCRCFAIL) - errors |= SDC_DATA_CRC_ERROR; - if (sta & SDIO_STA_CTIMEOUT) - errors |= SDC_COMMAND_TIMEOUT; - if (sta & SDIO_STA_DTIMEOUT) - errors |= SDC_DATA_TIMEOUT; - if (sta & SDIO_STA_TXUNDERR) - errors |= SDC_TX_UNDERRUN; - if (sta & SDIO_STA_RXOVERR) - errors |= SDC_RX_OVERRUN; - if (sta & SDIO_STA_STBITERR) - errors |= SDC_STARTBIT_ERROR; - - sdcp->errors |= errors; -} - -/** - * @brief Performs clean transaction stopping in case of errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @notapi - */ -static void sdc_lld_error_cleanup(SDCDriver *sdcp, - uint32_t n, - uint32_t *resp) { - uint32_t sta = sdcp->sdio->STA; - - dmaStreamClearInterrupt(sdcp->dma); - dmaStreamDisable(sdcp->dma); - sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; - sdcp->sdio->MASK = 0; - sdcp->sdio->DCTRL = 0; - sdc_lld_collect_errors(sdcp, sta); - if (n > 1) - sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if !defined(STM32_SDIO_HANDLER) -#error "STM32_SDIO_HANDLER not defined" -#endif -/** - * @brief SDIO IRQ handler. - * @details It just wakes transaction thread. All error handling performs in - * that thread. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SDIO_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - osalSysLockFromISR(); - - /* Disables the source but the status flags are not reset because the - read/write functions needs to check them.*/ - SDIO->MASK = 0; - - osalThreadResumeI(&SDCD1.thread, MSG_OK); - - osalSysUnlockFromISR(); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SDC driver initialization. - * - * @notapi - */ -void sdc_lld_init(void) { - - sdcObjectInit(&SDCD1); - SDCD1.thread = NULL; - SDCD1.dma = NULL; - SDCD1.sdio = SDIO; - nvicEnableVector(STM32_SDIO_NUMBER, STM32_SDC_SDIO_IRQ_PRIORITY); -} - -/** - * @brief Configures and activates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start(SDCDriver *sdcp) { - - /* Checking configuration, using a default if NULL has been passed.*/ - if (sdcp->config == NULL) { - sdcp->config = &sdc_default_cfg; - } - - sdcp->dmamode = STM32_DMA_CR_CHSEL(DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SDC_SDIO_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_WORD | - STM32_DMA_CR_MSIZE_WORD | - STM32_DMA_CR_MINC; - -#if (defined(STM32F4XX) || defined(STM32F2XX)) - sdcp->dmamode |= STM32_DMA_CR_PFCTRL | - STM32_DMA_CR_PBURST_INCR4 | - STM32_DMA_CR_MBURST_INCR4; -#endif - - if (sdcp->state == BLK_STOP) { - sdcp->dma = dmaStreamAllocI(STM32_SDC_SDIO_DMA_STREAM, - STM32_SDC_SDIO_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream"); - - dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdio->FIFO); -#if (defined(STM32F4XX) || defined(STM32F2XX)) - dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | STM32_DMA_FCR_FTH_FULL); -#endif - rccEnableSDIO(true); - } - - /* Configuration, card clock is initially stopped.*/ - sdcp->sdio->POWER = 0; - sdcp->sdio->CLKCR = 0; - sdcp->sdio->DCTRL = 0; - sdcp->sdio->DTIMER = 0; -} - -/** - * @brief Deactivates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop(SDCDriver *sdcp) { - - if (sdcp->state != BLK_STOP) { - - /* SDIO deactivation.*/ - sdcp->sdio->POWER = 0; - sdcp->sdio->CLKCR = 0; - sdcp->sdio->DCTRL = 0; - sdcp->sdio->DTIMER = 0; - - /* DMA stream released.*/ - dmaStreamFreeI(sdcp->dma); - sdcp->dma = NULL; - - /* Clock deactivation.*/ - rccDisableSDIO(); - } -} - -/** - * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start_clk(SDCDriver *sdcp) { - - /* Initial clock setting: 400kHz, 1bit mode.*/ - sdcp->sdio->CLKCR = STM32_SDIO_DIV_LS; - sdcp->sdio->POWER |= SDIO_POWER_PWRCTRL_0 | SDIO_POWER_PWRCTRL_1; - sdcp->sdio->CLKCR |= SDIO_CLKCR_CLKEN; - - /* Clock activation delay.*/ - osalThreadSleep(OSAL_MS2I(STM32_SDC_CLOCK_ACTIVATION_DELAY)); -} - -/** - * @brief Sets the SDIO clock to data mode (25MHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] clk the clock mode - * - * @notapi - */ -void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) { - -#if STM32_SDC_SDIO_50MHZ - if (SDC_CLK_50MHz == clk) { - sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS - | SDIO_CLKCR_BYPASS; - } - else - sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS; -#else - (void)clk; - - sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS; -#endif -} - -/** - * @brief Stops the SDIO clock. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop_clk(SDCDriver *sdcp) { - - sdcp->sdio->CLKCR = 0; - sdcp->sdio->POWER = 0; -} - -/** - * @brief Switches the bus to 4 bits mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] mode bus mode - * - * @notapi - */ -void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { - uint32_t clk = sdcp->sdio->CLKCR & ~SDIO_CLKCR_WIDBUS; - - switch (mode) { - case SDC_MODE_1BIT: - sdcp->sdio->CLKCR = clk; - break; - case SDC_MODE_4BIT: - sdcp->sdio->CLKCR = clk | SDIO_CLKCR_WIDBUS_0; - break; - case SDC_MODE_8BIT: - sdcp->sdio->CLKCR = clk | SDIO_CLKCR_WIDBUS_1; - break; - } -} - -/** - * @brief Sends an SDIO command with no response expected. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * - * @notapi - */ -void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { - - sdcp->sdio->ARG = arg; - sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_CPSMEN; - while ((sdcp->sdio->STA & SDIO_STA_CMDSENT) == 0) - ; - sdcp->sdio->ICR = SDIO_ICR_CMDSENTC; -} - -/** - * @brief Sends an SDIO command with a short response expected. - * @note The CRC is not verified. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - sdcp->sdio->ARG = arg; - sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; - while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL)) == 0) - ; - sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL); - if ((sta & (SDIO_STA_CTIMEOUT)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - *resp = sdcp->sdio->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a short response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - sdcp->sdio->ARG = arg; - sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; - while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL)) == 0) - ; - sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL); - if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - *resp = sdcp->sdio->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a long response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (four words) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - (void)sdcp; - - sdcp->sdio->ARG = arg; - sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_WAITRESP_1 | - SDIO_CMD_CPSMEN; - while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL)) == 0) - ; - sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL); - if ((sta & (STM32_SDIO_STA_ERROR_MASK)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - /* Save bytes in reverse order because MSB in response comes first.*/ - *resp++ = sdcp->sdio->RESP4; - *resp++ = sdcp->sdio->RESP3; - *resp++ = sdcp->sdio->RESP2; - *resp = sdcp->sdio->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Reads special registers using data bus. - * @details Needs only during card detection procedure. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] buf pointer to the read buffer - * @param[in] bytes number of bytes to read - * @param[in] cmd card command - * @param[in] arg argument for command - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, - uint8_t cmd, uint32_t arg) { - uint32_t resp[1]; - - if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes)) - goto error; - - if (sdc_lld_send_cmd_short_crc(sdcp, cmd, arg, resp) - || MMCSD_R1_ERROR(resp[0])) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, 1, resp)) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, 1, resp); - return HAL_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] blocks number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks) { - uint32_t resp[1]; - - osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); - - sdcp->sdio->DTIMER = STM32_SDC_READ_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, - (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; - sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | - SDIO_MASK_DTIMEOUTIE | - SDIO_MASK_STBITERRIE | - SDIO_MASK_RXOVERRIE | - SDIO_MASK_DATAENDIE; - sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE; - - /* Transaction starts just after DTEN bit setting.*/ - sdcp->sdio->DCTRL = SDIO_DCTRL_DTDIR | - SDIO_DCTRL_DBLOCKSIZE_3 | - SDIO_DCTRL_DBLOCKSIZE_0 | - SDIO_DCTRL_DMAEN | - SDIO_DCTRL_DTEN; - - if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, blocks, resp); - return HAL_FAILED; -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks) { - uint32_t resp[1]; - - osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); - - sdcp->sdio->DTIMER = STM32_SDC_WRITE_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for writing.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, - (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; - sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | - SDIO_MASK_DTIMEOUTIE | - SDIO_MASK_STBITERRIE | - SDIO_MASK_TXUNDERRIE | - SDIO_MASK_DATAENDIE; - sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE; - - /* Talk to card what we want from it.*/ - if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true) - goto error; - - /* Transaction starts just after DTEN bit setting.*/ - sdcp->sdio->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | - SDIO_DCTRL_DBLOCKSIZE_0 | - SDIO_DCTRL_DMAEN | - SDIO_DCTRL_DTEN; - - if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, blocks, resp); - return HAL_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] blocks number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks) { - -#if STM32_SDC_SDIO_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < blocks; i++) { - if (sdc_lld_read_aligned(sdcp, startblk, u.buf, 1)) - return HAL_FAILED; - memcpy(buf, u.buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - startblk++; - } - return HAL_SUCCESS; - } -#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); -#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_read_aligned(sdcp, startblk, buf, blocks); -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] blocks number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks) { - -#if STM32_SDC_SDIO_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < blocks; i++) { - memcpy(u.buf, buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - if (sdc_lld_write_aligned(sdcp, startblk, u.buf, 1)) - return HAL_FAILED; - startblk++; - } - return HAL_SUCCESS; - } -#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); -#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_write_aligned(sdcp, startblk, buf, blocks); -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool sdc_lld_sync(SDCDriver *sdcp) { - - /* CHTODO: Implement.*/ - (void)sdcp; - return HAL_SUCCESS; -} - -#endif /* HAL_USE_SDC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SDIOv1/hal_sdc_lld.c + * @brief STM32 SDC subsystem low level driver source. + * + * @addtogroup SDC + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SDC_SDIO_DMA_STREAM, \ + STM32_SDC_SDIO_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SDCD1 driver identifier.*/ +SDCDriver SDCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +#if STM32_SDC_SDIO_UNALIGNED_SUPPORT +/** + * @brief Buffer for temporary storage during unaligned transfers. + */ +static union { + uint32_t alignment; + uint8_t buf[MMCSD_BLOCK_SIZE]; +} u; +#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + +/** + * @brief SDIO default configuration. + */ +static const SDCConfig sdc_default_cfg = { + SDC_MODE_4BIT +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Prepares to handle read transaction. + * @details Designed for read special registers from card. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] buf pointer to the read buffer + * @param[in] bytes number of bytes to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp, + uint8_t *buf, uint32_t bytes) { + osalDbgCheck(bytes < 0x1000000); + + sdcp->sdio->DTIMER = STM32_SDC_READ_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, bytes / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; + sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | + SDIO_MASK_DTIMEOUTIE | + SDIO_MASK_STBITERRIE | + SDIO_MASK_RXOVERRIE | + SDIO_MASK_DATAENDIE; + sdcp->sdio->DLEN = bytes; + + /* Transaction starts just after DTEN bit setting.*/ + sdcp->sdio->DCTRL = SDIO_DCTRL_DTDIR | + SDIO_DCTRL_DTMODE | /* Multibyte data transfer.*/ + SDIO_DCTRL_DMAEN | + SDIO_DCTRL_DTEN; + + return HAL_SUCCESS; +} + +/** + * @brief Prepares card to handle read transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to read + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Send read multiple blocks command to card.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + else { + /* Send read single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Prepares card to handle write transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to write + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Write multiple blocks command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + else { + /* Write single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Wait end of data transaction and performs finalizations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + */ +static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, + uint32_t *resp) { + + /* Note the mask is checked before going to sleep because the interrupt + may have occurred before reaching the critical zone.*/ + osalSysLock(); + if (sdcp->sdio->MASK != 0) + osalThreadSuspendS(&sdcp->thread); + if ((sdcp->sdio->STA & SDIO_STA_DATAEND) == 0) { + osalSysUnlock(); + return HAL_FAILED; + } + +#if (defined(STM32F4XX) || defined(STM32F2XX)) + /* Wait until DMA channel enabled to be sure that all data transferred.*/ + while (sdcp->dma->stream->CR & STM32_DMA_CR_EN) + ; + + /* DMA event flags must be manually cleared.*/ + dmaStreamClearInterrupt(sdcp->dma); + + sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; + sdcp->sdio->DCTRL = 0; + osalSysUnlock(); +#else + /* Waits for transfer completion at DMA level, then the stream is + disabled and cleared.*/ + dmaWaitCompletion(sdcp->dma); + + sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; + sdcp->sdio->DCTRL = 0; + osalSysUnlock(); +#endif + + /* Finalize transaction.*/ + if (n > 1) + return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); + + return HAL_SUCCESS; +} + +/** + * @brief Gets SDC errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] sta value of the STA register + * + * @notapi + */ +static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { + uint32_t errors = SDC_NO_ERROR; + + if (sta & SDIO_STA_CCRCFAIL) + errors |= SDC_CMD_CRC_ERROR; + if (sta & SDIO_STA_DCRCFAIL) + errors |= SDC_DATA_CRC_ERROR; + if (sta & SDIO_STA_CTIMEOUT) + errors |= SDC_COMMAND_TIMEOUT; + if (sta & SDIO_STA_DTIMEOUT) + errors |= SDC_DATA_TIMEOUT; + if (sta & SDIO_STA_TXUNDERR) + errors |= SDC_TX_UNDERRUN; + if (sta & SDIO_STA_RXOVERR) + errors |= SDC_RX_OVERRUN; + if (sta & SDIO_STA_STBITERR) + errors |= SDC_STARTBIT_ERROR; + + sdcp->errors |= errors; +} + +/** + * @brief Performs clean transaction stopping in case of errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @notapi + */ +static void sdc_lld_error_cleanup(SDCDriver *sdcp, + uint32_t n, + uint32_t *resp) { + uint32_t sta = sdcp->sdio->STA; + + dmaStreamClearInterrupt(sdcp->dma); + dmaStreamDisable(sdcp->dma); + sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; + sdcp->sdio->MASK = 0; + sdcp->sdio->DCTRL = 0; + sdc_lld_collect_errors(sdcp, sta); + if (n > 1) + sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if !defined(STM32_SDIO_HANDLER) +#error "STM32_SDIO_HANDLER not defined" +#endif +/** + * @brief SDIO IRQ handler. + * @details It just wakes transaction thread. All error handling performs in + * that thread. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SDIO_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + + /* Disables the source but the status flags are not reset because the + read/write functions needs to check them.*/ + SDIO->MASK = 0; + + osalThreadResumeI(&SDCD1.thread, MSG_OK); + + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SDC driver initialization. + * + * @notapi + */ +void sdc_lld_init(void) { + + sdcObjectInit(&SDCD1); + SDCD1.thread = NULL; + SDCD1.dma = NULL; + SDCD1.sdio = SDIO; + nvicEnableVector(STM32_SDIO_NUMBER, STM32_SDC_SDIO_IRQ_PRIORITY); +} + +/** + * @brief Configures and activates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start(SDCDriver *sdcp) { + + /* Checking configuration, using a default if NULL has been passed.*/ + if (sdcp->config == NULL) { + sdcp->config = &sdc_default_cfg; + } + + sdcp->dmamode = STM32_DMA_CR_CHSEL(DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SDC_SDIO_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_WORD | + STM32_DMA_CR_MSIZE_WORD | + STM32_DMA_CR_MINC; + +#if (defined(STM32F4XX) || defined(STM32F2XX)) + sdcp->dmamode |= STM32_DMA_CR_PFCTRL | + STM32_DMA_CR_PBURST_INCR4 | + STM32_DMA_CR_MBURST_INCR4; +#endif + + if (sdcp->state == BLK_STOP) { + sdcp->dma = dmaStreamAllocI(STM32_SDC_SDIO_DMA_STREAM, + STM32_SDC_SDIO_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream"); + + dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdio->FIFO); +#if (defined(STM32F4XX) || defined(STM32F2XX)) + dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | STM32_DMA_FCR_FTH_FULL); +#endif + rccEnableSDIO(true); + } + + /* Configuration, card clock is initially stopped.*/ + sdcp->sdio->POWER = 0; + sdcp->sdio->CLKCR = 0; + sdcp->sdio->DCTRL = 0; + sdcp->sdio->DTIMER = 0; +} + +/** + * @brief Deactivates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop(SDCDriver *sdcp) { + + if (sdcp->state != BLK_STOP) { + + /* SDIO deactivation.*/ + sdcp->sdio->POWER = 0; + sdcp->sdio->CLKCR = 0; + sdcp->sdio->DCTRL = 0; + sdcp->sdio->DTIMER = 0; + + /* DMA stream released.*/ + dmaStreamFreeI(sdcp->dma); + sdcp->dma = NULL; + + /* Clock deactivation.*/ + rccDisableSDIO(); + } +} + +/** + * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start_clk(SDCDriver *sdcp) { + + /* Initial clock setting: 400kHz, 1bit mode.*/ + sdcp->sdio->CLKCR = STM32_SDIO_DIV_LS; + sdcp->sdio->POWER |= SDIO_POWER_PWRCTRL_0 | SDIO_POWER_PWRCTRL_1; + sdcp->sdio->CLKCR |= SDIO_CLKCR_CLKEN; + + /* Clock activation delay.*/ + osalThreadSleep(OSAL_MS2I(STM32_SDC_CLOCK_ACTIVATION_DELAY)); +} + +/** + * @brief Sets the SDIO clock to data mode (25MHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] clk the clock mode + * + * @notapi + */ +void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) { + +#if STM32_SDC_SDIO_50MHZ + if (SDC_CLK_50MHz == clk) { + sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS + | SDIO_CLKCR_BYPASS; + } + else + sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS; +#else + (void)clk; + + sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS; +#endif +} + +/** + * @brief Stops the SDIO clock. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop_clk(SDCDriver *sdcp) { + + sdcp->sdio->CLKCR = 0; + sdcp->sdio->POWER = 0; +} + +/** + * @brief Switches the bus to 4 bits mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] mode bus mode + * + * @notapi + */ +void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { + uint32_t clk = sdcp->sdio->CLKCR & ~SDIO_CLKCR_WIDBUS; + + switch (mode) { + case SDC_MODE_1BIT: + sdcp->sdio->CLKCR = clk; + break; + case SDC_MODE_4BIT: + sdcp->sdio->CLKCR = clk | SDIO_CLKCR_WIDBUS_0; + break; + case SDC_MODE_8BIT: + sdcp->sdio->CLKCR = clk | SDIO_CLKCR_WIDBUS_1; + break; + } +} + +/** + * @brief Sends an SDIO command with no response expected. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * + * @notapi + */ +void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { + + sdcp->sdio->ARG = arg; + sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_CPSMEN; + while ((sdcp->sdio->STA & SDIO_STA_CMDSENT) == 0) + ; + sdcp->sdio->ICR = SDIO_ICR_CMDSENTC; +} + +/** + * @brief Sends an SDIO command with a short response expected. + * @note The CRC is not verified. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + sdcp->sdio->ARG = arg; + sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; + while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL)) == 0) + ; + sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL); + if ((sta & (SDIO_STA_CTIMEOUT)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + *resp = sdcp->sdio->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a short response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + sdcp->sdio->ARG = arg; + sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; + while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL)) == 0) + ; + sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL); + if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + *resp = sdcp->sdio->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a long response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (four words) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + (void)sdcp; + + sdcp->sdio->ARG = arg; + sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_WAITRESP_1 | + SDIO_CMD_CPSMEN; + while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL)) == 0) + ; + sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL); + if ((sta & (STM32_SDIO_STA_ERROR_MASK)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + /* Save bytes in reverse order because MSB in response comes first.*/ + *resp++ = sdcp->sdio->RESP4; + *resp++ = sdcp->sdio->RESP3; + *resp++ = sdcp->sdio->RESP2; + *resp = sdcp->sdio->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Reads special registers using data bus. + * @details Needs only during card detection procedure. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] buf pointer to the read buffer + * @param[in] bytes number of bytes to read + * @param[in] cmd card command + * @param[in] arg argument for command + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, + uint8_t cmd, uint32_t arg) { + uint32_t resp[1]; + + if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes)) + goto error; + + if (sdc_lld_send_cmd_short_crc(sdcp, cmd, arg, resp) + || MMCSD_R1_ERROR(resp[0])) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, 1, resp)) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, 1, resp); + return HAL_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] blocks number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks) { + uint32_t resp[1]; + + osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); + + sdcp->sdio->DTIMER = STM32_SDC_READ_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, + (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; + sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | + SDIO_MASK_DTIMEOUTIE | + SDIO_MASK_STBITERRIE | + SDIO_MASK_RXOVERRIE | + SDIO_MASK_DATAENDIE; + sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE; + + /* Transaction starts just after DTEN bit setting.*/ + sdcp->sdio->DCTRL = SDIO_DCTRL_DTDIR | + SDIO_DCTRL_DBLOCKSIZE_3 | + SDIO_DCTRL_DBLOCKSIZE_0 | + SDIO_DCTRL_DMAEN | + SDIO_DCTRL_DTEN; + + if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, blocks, resp); + return HAL_FAILED; +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks) { + uint32_t resp[1]; + + osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); + + sdcp->sdio->DTIMER = STM32_SDC_WRITE_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for writing.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, + (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS; + sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE | + SDIO_MASK_DTIMEOUTIE | + SDIO_MASK_STBITERRIE | + SDIO_MASK_TXUNDERRIE | + SDIO_MASK_DATAENDIE; + sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE; + + /* Talk to card what we want from it.*/ + if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true) + goto error; + + /* Transaction starts just after DTEN bit setting.*/ + sdcp->sdio->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | + SDIO_DCTRL_DBLOCKSIZE_0 | + SDIO_DCTRL_DMAEN | + SDIO_DCTRL_DTEN; + + if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, blocks, resp); + return HAL_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] blocks number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks) { + +#if STM32_SDC_SDIO_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < blocks; i++) { + if (sdc_lld_read_aligned(sdcp, startblk, u.buf, 1)) + return HAL_FAILED; + memcpy(buf, u.buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + startblk++; + } + return HAL_SUCCESS; + } +#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); +#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_read_aligned(sdcp, startblk, buf, blocks); +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] blocks number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks) { + +#if STM32_SDC_SDIO_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < blocks; i++) { + memcpy(u.buf, buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + if (sdc_lld_write_aligned(sdcp, startblk, u.buf, 1)) + return HAL_FAILED; + startblk++; + } + return HAL_SUCCESS; + } +#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); +#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_write_aligned(sdcp, startblk, buf, blocks); +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdc_lld_sync(SDCDriver *sdcp) { + + /* CHTODO: Implement.*/ + (void)sdcp; + return HAL_SUCCESS; +} + +#endif /* HAL_USE_SDC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h b/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h index 4f0a430739..f20beb4e44 100644 --- a/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h +++ b/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h @@ -1,353 +1,353 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SDIOv1/hal_sdc_lld.h - * @brief STM32 SDC subsystem low level driver header. - * - * @addtogroup SDC - * @{ - */ - -#ifndef HAL_SDC_LLD_H -#define HAL_SDC_LLD_H - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* - * The following definitions are missing from some implementations, fixing - * as zeroed masks. - */ -#if !defined(SDIO_STA_STBITERR) -#define SDIO_STA_STBITERR 0 -#endif - -#if !defined(SDIO_ICR_STBITERRC) -#define SDIO_ICR_STBITERRC 0 -#endif - -#if !defined(SDIO_ICR_CEATAENDC) -#define SDIO_ICR_CEATAENDC 0 -#endif - -#if !defined(SDIO_MASK_STBITERRIE) -#define SDIO_MASK_STBITERRIE 0 -#endif - -/** - * @brief Value to clear all interrupts flag at once. - */ -#define STM32_SDIO_ICR_ALL_FLAGS (SDIO_ICR_CCRCFAILC | SDIO_ICR_DCRCFAILC | \ - SDIO_ICR_CTIMEOUTC | SDIO_ICR_DTIMEOUTC | \ - SDIO_ICR_TXUNDERRC | SDIO_ICR_RXOVERRC | \ - SDIO_ICR_CMDRENDC | SDIO_ICR_CMDSENTC | \ - SDIO_ICR_DATAENDC | SDIO_ICR_STBITERRC | \ - SDIO_ICR_DBCKENDC | SDIO_ICR_SDIOITC | \ - SDIO_ICR_CEATAENDC) - -/** - * @brief Mask of error flags in STA register. - */ -#define STM32_SDIO_STA_ERROR_MASK (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | \ - SDIO_STA_CTIMEOUT | SDIO_STA_DTIMEOUT | \ - SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR) - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SDIO DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_SDC_SDIO_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_DMA_PRIORITY 3 -#endif - -/** - * @brief SDIO interrupt priority level setting. - */ -#if !defined(STM32_SDC_SDIO_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_IRQ_PRIORITY 9 -#endif - -/** - * @brief Enable clock bypass. - * @note Allow clock speed up to 50 Mhz. - */ -#if !defined(STM32_SDC_SDIO_50MHZ) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_50MHZ FALSE -#endif - -/** - * @brief Write timeout in milliseconds. - */ -#if !defined(STM32_SDC_WRITE_TIMEOUT_MS) || defined(__DOXYGEN__) -#define STM32_SDC_WRITE_TIMEOUT_MS 1000 -#endif - -/** - * @brief Read timeout in milliseconds. - */ -#if !defined(STM32_SDC_READ_TIMEOUT_MS) || defined(__DOXYGEN__) -#define STM32_SDC_READ_TIMEOUT_MS 1000 -#endif - -/** - * @brief Card clock activation delay in milliseconds. - */ -#if !defined(STM32_SDC_CLOCK_ACTIVATION_DELAY) || defined(__DOXYGEN__) -#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 -#endif - -/** - * @brief Support for unaligned transfers. - * @note Unaligned transfers are much slower. - */ -#if !defined(STM32_SDC_SDIO_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !STM32_HAS_SDIO -#error "SDIO not present in the selected device" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDIO_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDIO" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDIO_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDIO" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if !defined(STM32_SDC_SDIO_DMA_STREAM) -#error "SDIO DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if !STM32_DMA_IS_VALID_ID(STM32_SDC_SDIO_DMA_STREAM, STM32_SDC_SDIO_DMA_MSK) -#error "invalid DMA stream associated to SDIO" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/* - * SDIO clock divider. - */ -#if (defined(STM32F4XX) || defined(STM32F2XX)) -#define STM32_SDIO_DIV_HS 0 -#define STM32_SDIO_DIV_LS 120 - -#elif STM32_HCLK > 48000000 -#define STM32_SDIO_DIV_HS 1 -#define STM32_SDIO_DIV_LS 178 -#else - -#define STM32_SDIO_DIV_HS 0 -#define STM32_SDIO_DIV_LS 118 -#endif - -/** - * @brief SDIO data timeouts in SDIO clock cycles. - */ -#if (defined(STM32F4XX) || defined(STM32F2XX)) -#if !STM32_CLOCK48_REQUIRED -#error "SDIO requires STM32_CLOCK48_REQUIRED to be enabled" -#endif - -#if STM32_PLL48CLK != 48000000 -#error "invalid STM32_PLL48CLK clock value" -#endif - -#define STM32_SDC_WRITE_TIMEOUT \ - (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ - STM32_SDC_WRITE_TIMEOUT_MS) -#define STM32_SDC_READ_TIMEOUT \ - (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ - STM32_SDC_READ_TIMEOUT_MS) - -#else /* !(defined(STM32F4XX) || defined(STM32F2XX)) */ - -#define STM32_SDC_WRITE_TIMEOUT \ - (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ - STM32_SDC_WRITE_TIMEOUT_MS) -#define STM32_SDC_READ_TIMEOUT \ - (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ - STM32_SDC_READ_TIMEOUT_MS) - -#endif /* !(defined(STM32F4XX) || defined(STM32F2XX)) */ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of card flags. - */ -typedef uint32_t sdcmode_t; - -/** - * @brief SDC Driver condition flags type. - */ -typedef uint32_t sdcflags_t; - -/** - * @brief Type of a structure representing an SDC driver. - */ -typedef struct SDCDriver SDCDriver; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Bus width. - */ - sdcbusmode_t bus_width; - /* End of the mandatory fields.*/ -} SDCConfig; - -/** - * @brief @p SDCDriver specific methods. - */ -#define _sdc_driver_methods \ - _mmcsd_block_device_methods - -/** - * @extends MMCSDBlockDeviceVMT - * - * @brief @p SDCDriver virtual methods table. - */ -struct SDCDriverVMT { - _sdc_driver_methods -}; - -/** - * @brief Structure representing an SDC driver. - */ -struct SDCDriver { - /** - * @brief Virtual Methods Table. - */ - const struct SDCDriverVMT *vmt; - _mmcsd_block_device_data - /** - * @brief Current configuration data. - */ - const SDCConfig *config; - /** - * @brief Various flags regarding the mounted card. - */ - sdcmode_t cardmode; - /** - * @brief Errors flags. - */ - sdcflags_t errors; - /** - * @brief Card RCA. - */ - uint32_t rca; - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion IRQ. - */ - thread_reference_t thread; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dma; - /** - * @brief Pointer to the SDIO registers block. - * @note Needed for debugging aid. - */ - SDIO_TypeDef *sdio; - /** - * @brief Buffer for internal operations. - */ - uint8_t buf[MMCSD_BLOCK_SIZE]; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern SDCDriver SDCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sdc_lld_init(void); - void sdc_lld_start(SDCDriver *sdcp); - void sdc_lld_stop(SDCDriver *sdcp); - void sdc_lld_start_clk(SDCDriver *sdcp); - void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk); - void sdc_lld_stop_clk(SDCDriver *sdcp); - void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); - void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); - bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, - uint8_t cmd, uint32_t argument); - bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks); - bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks); - bool sdc_lld_sync(SDCDriver *sdcp); - bool sdc_lld_is_card_inserted(SDCDriver *sdcp); - bool sdc_lld_is_write_protected(SDCDriver *sdcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SDC */ - -#endif /* HAL_SDC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SDIOv1/hal_sdc_lld.h + * @brief STM32 SDC subsystem low level driver header. + * + * @addtogroup SDC + * @{ + */ + +#ifndef HAL_SDC_LLD_H +#define HAL_SDC_LLD_H + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * The following definitions are missing from some implementations, fixing + * as zeroed masks. + */ +#if !defined(SDIO_STA_STBITERR) +#define SDIO_STA_STBITERR 0 +#endif + +#if !defined(SDIO_ICR_STBITERRC) +#define SDIO_ICR_STBITERRC 0 +#endif + +#if !defined(SDIO_ICR_CEATAENDC) +#define SDIO_ICR_CEATAENDC 0 +#endif + +#if !defined(SDIO_MASK_STBITERRIE) +#define SDIO_MASK_STBITERRIE 0 +#endif + +/** + * @brief Value to clear all interrupts flag at once. + */ +#define STM32_SDIO_ICR_ALL_FLAGS (SDIO_ICR_CCRCFAILC | SDIO_ICR_DCRCFAILC | \ + SDIO_ICR_CTIMEOUTC | SDIO_ICR_DTIMEOUTC | \ + SDIO_ICR_TXUNDERRC | SDIO_ICR_RXOVERRC | \ + SDIO_ICR_CMDRENDC | SDIO_ICR_CMDSENTC | \ + SDIO_ICR_DATAENDC | SDIO_ICR_STBITERRC | \ + SDIO_ICR_DBCKENDC | SDIO_ICR_SDIOITC | \ + SDIO_ICR_CEATAENDC) + +/** + * @brief Mask of error flags in STA register. + */ +#define STM32_SDIO_STA_ERROR_MASK (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | \ + SDIO_STA_CTIMEOUT | SDIO_STA_DTIMEOUT | \ + SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SDIO DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_SDC_SDIO_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#endif + +/** + * @brief SDIO interrupt priority level setting. + */ +#if !defined(STM32_SDC_SDIO_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#endif + +/** + * @brief Enable clock bypass. + * @note Allow clock speed up to 50 Mhz. + */ +#if !defined(STM32_SDC_SDIO_50MHZ) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_50MHZ FALSE +#endif + +/** + * @brief Write timeout in milliseconds. + */ +#if !defined(STM32_SDC_WRITE_TIMEOUT_MS) || defined(__DOXYGEN__) +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#endif + +/** + * @brief Read timeout in milliseconds. + */ +#if !defined(STM32_SDC_READ_TIMEOUT_MS) || defined(__DOXYGEN__) +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#endif + +/** + * @brief Card clock activation delay in milliseconds. + */ +#if !defined(STM32_SDC_CLOCK_ACTIVATION_DELAY) || defined(__DOXYGEN__) +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#endif + +/** + * @brief Support for unaligned transfers. + * @note Unaligned transfers are much slower. + */ +#if !defined(STM32_SDC_SDIO_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !STM32_HAS_SDIO +#error "SDIO not present in the selected device" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDIO_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDIO" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDIO_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDIO" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if !defined(STM32_SDC_SDIO_DMA_STREAM) +#error "SDIO DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if !STM32_DMA_IS_VALID_ID(STM32_SDC_SDIO_DMA_STREAM, STM32_SDC_SDIO_DMA_MSK) +#error "invalid DMA stream associated to SDIO" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* + * SDIO clock divider. + */ +#if (defined(STM32F4XX) || defined(STM32F2XX)) +#define STM32_SDIO_DIV_HS 0 +#define STM32_SDIO_DIV_LS 120 + +#elif STM32_HCLK > 48000000 +#define STM32_SDIO_DIV_HS 1 +#define STM32_SDIO_DIV_LS 178 +#else + +#define STM32_SDIO_DIV_HS 0 +#define STM32_SDIO_DIV_LS 118 +#endif + +/** + * @brief SDIO data timeouts in SDIO clock cycles. + */ +#if (defined(STM32F4XX) || defined(STM32F2XX)) +#if !STM32_CLOCK48_REQUIRED +#error "SDIO requires STM32_CLOCK48_REQUIRED to be enabled" +#endif + +#if STM32_PLL48CLK != 48000000 +#error "invalid STM32_PLL48CLK clock value" +#endif + +#define STM32_SDC_WRITE_TIMEOUT \ + (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ + STM32_SDC_WRITE_TIMEOUT_MS) +#define STM32_SDC_READ_TIMEOUT \ + (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ + STM32_SDC_READ_TIMEOUT_MS) + +#else /* !(defined(STM32F4XX) || defined(STM32F2XX)) */ + +#define STM32_SDC_WRITE_TIMEOUT \ + (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ + STM32_SDC_WRITE_TIMEOUT_MS) +#define STM32_SDC_READ_TIMEOUT \ + (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \ + STM32_SDC_READ_TIMEOUT_MS) + +#endif /* !(defined(STM32F4XX) || defined(STM32F2XX)) */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of card flags. + */ +typedef uint32_t sdcmode_t; + +/** + * @brief SDC Driver condition flags type. + */ +typedef uint32_t sdcflags_t; + +/** + * @brief Type of a structure representing an SDC driver. + */ +typedef struct SDCDriver SDCDriver; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Bus width. + */ + sdcbusmode_t bus_width; + /* End of the mandatory fields.*/ +} SDCConfig; + +/** + * @brief @p SDCDriver specific methods. + */ +#define _sdc_driver_methods \ + _mmcsd_block_device_methods + +/** + * @extends MMCSDBlockDeviceVMT + * + * @brief @p SDCDriver virtual methods table. + */ +struct SDCDriverVMT { + _sdc_driver_methods +}; + +/** + * @brief Structure representing an SDC driver. + */ +struct SDCDriver { + /** + * @brief Virtual Methods Table. + */ + const struct SDCDriverVMT *vmt; + _mmcsd_block_device_data + /** + * @brief Current configuration data. + */ + const SDCConfig *config; + /** + * @brief Various flags regarding the mounted card. + */ + sdcmode_t cardmode; + /** + * @brief Errors flags. + */ + sdcflags_t errors; + /** + * @brief Card RCA. + */ + uint32_t rca; + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion IRQ. + */ + thread_reference_t thread; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dma; + /** + * @brief Pointer to the SDIO registers block. + * @note Needed for debugging aid. + */ + SDIO_TypeDef *sdio; + /** + * @brief Buffer for internal operations. + */ + uint8_t buf[MMCSD_BLOCK_SIZE]; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern SDCDriver SDCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sdc_lld_init(void); + void sdc_lld_start(SDCDriver *sdcp); + void sdc_lld_stop(SDCDriver *sdcp); + void sdc_lld_start_clk(SDCDriver *sdcp); + void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk); + void sdc_lld_stop_clk(SDCDriver *sdcp); + void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); + void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); + bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, + uint8_t cmd, uint32_t argument); + bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks); + bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks); + bool sdc_lld_sync(SDCDriver *sdcp); + bool sdc_lld_is_card_inserted(SDCDriver *sdcp); + bool sdc_lld_is_write_protected(SDCDriver *sdcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SDC */ + +#endif /* HAL_SDC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk b/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk index 7edbc24389..7f0658c698 100644 --- a/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk +++ b/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1 diff --git a/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c b/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c index 1544981f7a..12c20d9db2 100644 --- a/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c +++ b/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c @@ -1,981 +1,981 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SDMMCv1/hal_sdc_lld.c - * @brief STM32 SDC subsystem low level driver source. - * - * @addtogroup SDC - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SDMMC_ICR_ALL_FLAGS \ - (SDMMC_ICR_CCRCFAILC | SDMMC_ICR_DCRCFAILC | \ - SDMMC_ICR_CTIMEOUTC | SDMMC_ICR_DTIMEOUTC | \ - SDMMC_ICR_TXUNDERRC | SDMMC_ICR_RXOVERRC | \ - SDMMC_ICR_CMDRENDC | SDMMC_ICR_CMDSENTC | \ - SDMMC_ICR_DATAENDC | SDMMC_ICR_DBCKENDC | \ - SDMMC_ICR_SDIOITC) - -#define SDMMC_STA_ERROR_MASK \ - (SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | \ - SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | \ - SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR) - -#define SDMMC_CLKDIV_HS (2 - 2) -#define SDMMC_CLKDIV_LS (120 - 2) - -#define SDMMC1_WRITE_TIMEOUT \ - (((STM32_SDMMC1CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ - STM32_SDC_SDMMC_WRITE_TIMEOUT) -#define SDMMC1_READ_TIMEOUT \ - (((STM32_SDMMC1CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ - STM32_SDC_SDMMC_READ_TIMEOUT) - -#define SDMMC2_WRITE_TIMEOUT \ - (((STM32_SDMMC2CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ - STM32_SDC_SDMMC_WRITE_TIMEOUT) -#define SDMMC2_READ_TIMEOUT \ - (((STM32_SDMMC2CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ - STM32_SDC_SDMMC_READ_TIMEOUT) - -#define SDMMC1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SDC_SDMMC1_DMA_STREAM, \ - STM32_SDC_SDMMC1_DMA_CHN) - -#define SDMMC2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SDC_SDMMC2_DMA_STREAM, \ - STM32_SDC_SDMMC2_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SDCD1 driver identifier.*/ -#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__) -SDCDriver SDCD1; -#endif - -/** @brief SDCD2 driver identifier.*/ -#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__) -SDCDriver SDCD2; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief SDIO default configuration. - */ -static const SDCConfig sdc_default_cfg = { - SDC_MODE_4BIT -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Prepares to handle read transaction. - * @details Designed for read special registers from card. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] buf pointer to the read buffer - * @param[in] bytes number of bytes to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp, - uint8_t *buf, uint32_t bytes) { - osalDbgCheck(bytes < 0x1000000); - - sdcp->sdmmc->DTIMER = sdcp->rtmo; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, bytes / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | - SDMMC_MASK_DTIMEOUTIE | - SDMMC_MASK_RXOVERRIE | - SDMMC_MASK_DATAENDIE; - sdcp->sdmmc->DLEN = bytes; - - /* Transaction starts just after DTEN bit setting.*/ - sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | - SDMMC_DCTRL_DTMODE | /* Multibyte data transfer.*/ - SDMMC_DCTRL_DMAEN | - SDMMC_DCTRL_DTEN; - - return HAL_SUCCESS; -} - -/** - * @brief Prepares card to handle read transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to read - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Send read multiple blocks command to card.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - else { - /* Send read single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Prepares card to handle write transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to write - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Write multiple blocks command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - else { - /* Write single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Wait end of data transaction and performs finalizations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - */ -static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, - uint32_t *resp) { - - /* Note the mask is checked before going to sleep because the interrupt - may have occurred before reaching the critical zone.*/ - osalSysLock(); - if (sdcp->sdmmc->MASK != 0) - osalThreadSuspendS(&sdcp->thread); - if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) { - osalSysUnlock(); - return HAL_FAILED; - } - - /* Waits for transfer completion at DMA level, then the stream is - disabled and cleared.*/ - dmaWaitCompletion(sdcp->dma); - - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->DCTRL = 0; - osalSysUnlock(); - - /* Finalize transaction.*/ - if (n > 1) - return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); - - return HAL_SUCCESS; -} - -/** - * @brief Gets SDC errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] sta value of the STA register - * - * @notapi - */ -static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { - uint32_t errors = SDC_NO_ERROR; - - if (sta & SDMMC_STA_CCRCFAIL) - errors |= SDC_CMD_CRC_ERROR; - if (sta & SDMMC_STA_DCRCFAIL) - errors |= SDC_DATA_CRC_ERROR; - if (sta & SDMMC_STA_CTIMEOUT) - errors |= SDC_COMMAND_TIMEOUT; - if (sta & SDMMC_STA_DTIMEOUT) - errors |= SDC_DATA_TIMEOUT; - if (sta & SDMMC_STA_TXUNDERR) - errors |= SDC_TX_UNDERRUN; - if (sta & SDMMC_STA_RXOVERR) - errors |= SDC_RX_OVERRUN; -/* if (sta & SDMMC_STA_STBITERR) - errors |= SDC_STARTBIT_ERROR;*/ - - sdcp->errors |= errors; -} - -/** - * @brief Performs clean transaction stopping in case of errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @notapi - */ -static void sdc_lld_error_cleanup(SDCDriver *sdcp, - uint32_t n, - uint32_t *resp) { - uint32_t sta = sdcp->sdmmc->STA; - - dmaStreamDisable(sdcp->dma); - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = 0; - sdcp->sdmmc->DCTRL = 0; - sdc_lld_collect_errors(sdcp, sta); - - if (n > 1) - sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief SDMMC1 IRQ handler. - * @details It just wakes transaction thread, errors handling is performed in - * there. - * - * @isr - */ -#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__) -OSAL_IRQ_HANDLER(STM32_SDMMC1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - osalSysLockFromISR(); - - /* Disables the source but the status flags are not reset because the - read/write functions needs to check them.*/ - SDMMC1->MASK = 0; - - osalThreadResumeI(&SDCD1.thread, MSG_OK); - - osalSysUnlockFromISR(); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/** - * @brief SDMMC2 IRQ handler. - * @details It just wakes transaction thread, errors handling is performed in - * there. - * - * @isr - */ -#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__) -OSAL_IRQ_HANDLER(STM32_SDMMC2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - osalSysLockFromISR(); - - /* Disables the source but the status flags are not reset because the - read/write functions needs to check them.*/ - SDMMC2->MASK = 0; - - osalThreadResumeI(&SDCD2.thread, MSG_OK); - - osalSysUnlockFromISR(); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SDC driver initialization. - * - * @notapi - */ -void sdc_lld_init(void) { - -#if STM32_SDC_USE_SDMMC1 - sdcObjectInit(&SDCD1); - SDCD1.thread = NULL; - SDCD1.rtmo = SDMMC1_READ_TIMEOUT; - SDCD1.wtmo = SDMMC1_WRITE_TIMEOUT; - SDCD1.dma = NULL; - SDCD1.sdmmc = SDMMC1; - nvicEnableVector(STM32_SDMMC1_NUMBER, STM32_SDC_SDMMC1_IRQ_PRIORITY); -#endif - -#if STM32_SDC_USE_SDMMC2 - sdcObjectInit(&SDCD2); - SDCD2.thread = NULL; - SDCD2.rtmo = SDMMC2_READ_TIMEOUT; - SDCD2.wtmo = SDMMC2_WRITE_TIMEOUT; - SDCD2.dma = NULL; - SDCD2.sdmmc = SDMMC2; - nvicEnableVector(STM32_SDMMC2_NUMBER, STM32_SDC_SDMMC2_IRQ_PRIORITY); -#endif -} - -/** - * @brief Configures and activates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start(SDCDriver *sdcp) { - - /* Checking configuration, using a default if NULL has been passed.*/ - if (sdcp->config == NULL) { - sdcp->config = &sdc_default_cfg; - } - - sdcp->dmamode = STM32_DMA_CR_PSIZE_WORD | - STM32_DMA_CR_MSIZE_WORD | - STM32_DMA_CR_MINC; - -#if STM32_DMA_ADVANCED - sdcp->dmamode |= STM32_DMA_CR_PFCTRL | - STM32_DMA_CR_PBURST_INCR4 | - STM32_DMA_CR_MBURST_INCR4; -#endif - - /* If in stopped state then clocks are enabled and DMA initialized.*/ - if (sdcp->state == BLK_STOP) { -#if STM32_SDC_USE_SDMMC1 - if (&SDCD1 == sdcp) { - sdcp->dma = dmaStreamAllocI(STM32_SDC_SDMMC1_DMA_STREAM, - STM32_SDC_SDMMC1_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream"); - - sdcp->dmamode |= STM32_DMA_CR_CHSEL(SDMMC1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SDC_SDMMC1_DMA_PRIORITY); - dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdmmc->FIFO); -#if STM32_DMA_ADVANCED - dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | - STM32_DMA_FCR_FTH_FULL); -#endif - rccEnableSDMMC1(true); - } -#endif /* STM32_SDC_USE_SDMMC1 */ - -#if STM32_SDC_USE_SDMMC2 - if (&SDCD2 == sdcp) { - sdcp->dma = dmaStreamAllocI(STM32_SDC_SDMMC2_DMA_STREAM, - STM32_SDC_SDMMC2_IRQ_PRIORITY, - NULL, - NULL); - osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream"); - - sdcp->dmamode |= STM32_DMA_CR_CHSEL(SDMMC2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SDC_SDMMC2_DMA_PRIORITY); - dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdmmc->FIFO); -#if STM32_DMA_ADVANCED - dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | - STM32_DMA_FCR_FTH_FULL); -#endif - rccEnableSDMMC2(true); - } -#endif /* STM32_SDC_USE_SDMMC2 */ - } - - /* Configuration, card clock is initially stopped.*/ - sdcp->sdmmc->POWER = 0; - sdcp->sdmmc->CLKCR = 0; - sdcp->sdmmc->DCTRL = 0; - sdcp->sdmmc->DTIMER = 0; -} - -/** - * @brief Deactivates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop(SDCDriver *sdcp) { - - if (sdcp->state != BLK_STOP) { - - /* SDIO deactivation.*/ - sdcp->sdmmc->POWER = 0; - sdcp->sdmmc->CLKCR = 0; - sdcp->sdmmc->DCTRL = 0; - sdcp->sdmmc->DTIMER = 0; - - /* DMA stream released.*/ - dmaStreamFreeI(sdcp->dma); - sdcp->dma = NULL; - - /* Clock deactivation.*/ -#if STM32_SDC_USE_SDMMC1 - if (&SDCD1 == sdcp) { - rccDisableSDMMC1(); - } -#endif - -#if STM32_SDC_USE_SDMMC2 - if (&SDCD2 == sdcp) { - rccDisableSDMMC2(); - } -#endif - } -} - -/** - * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start_clk(SDCDriver *sdcp) { - - /* Initial clock setting: 400kHz, 1bit mode.*/ - sdcp->sdmmc->CLKCR = SDMMC_CLKDIV_LS; - sdcp->sdmmc->POWER |= SDMMC_POWER_PWRCTRL_0 | SDMMC_POWER_PWRCTRL_1; - sdcp->sdmmc->CLKCR |= SDMMC_CLKCR_CLKEN; - - /* Clock activation delay.*/ - osalThreadSleep(OSAL_MS2I(STM32_SDC_SDMMC_CLOCK_DELAY)); -} - -/** - * @brief Sets the SDIO clock to data mode (25/50 MHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] clk the clock mode - * - * @notapi - */ -void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) { - -#if STM32_SDC_SDMMC_50MHZ - if (SDC_CLK_50MHz == clk) { - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | -#if STM32_SDC_SDMMC_PWRSAV - SDMMC_CLKDIV_HS | SDMMC_CLKCR_BYPASS | - SDMMC_CLKCR_PWRSAV; -#else - SDMMC_CLKDIV_HS | SDMMC_CLKCR_BYPASS; -#endif - } - else { -#if STM32_SDC_SDMMC_PWRSAV - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS | - SDMMC_CLKCR_PWRSAV; -#else - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS; -#endif - } -#else - (void)clk; - -#if STM32_SDC_SDMMC_PWRSAV - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS | - SDMMC_CLKCR_PWRSAV; -#else - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS; -#endif -#endif -} - -/** - * @brief Stops the SDIO clock. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop_clk(SDCDriver *sdcp) { - - sdcp->sdmmc->CLKCR = 0; - sdcp->sdmmc->POWER = 0; -} - -/** - * @brief Switches the bus to 1, 4 or 8 bits mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] mode bus mode - * - * @notapi - */ -void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { - uint32_t clk = sdcp->sdmmc->CLKCR & ~SDMMC_CLKCR_WIDBUS; - - switch (mode) { - case SDC_MODE_1BIT: - sdcp->sdmmc->CLKCR = clk; - break; - case SDC_MODE_4BIT: - sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_0; - break; - case SDC_MODE_8BIT: - sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_1; - break; - } -} - -/** - * @brief Sends an SDIO command with no response expected. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * - * @notapi - */ -void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_CPSMEN; - while ((sdcp->sdmmc->STA & SDMMC_STA_CMDSENT) == 0) - ; - sdcp->sdmmc->ICR = SDMMC_ICR_CMDSENTC; -} - -/** - * @brief Sends an SDIO command with a short response expected. - * @note The CRC is not verified. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; - while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL)) == 0) - ; - sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL); - if ((sta & (SDMMC_STA_CTIMEOUT)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - *resp = sdcp->sdmmc->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a short response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; - while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL)) == 0) - ; - sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL); - if ((sta & (SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - *resp = sdcp->sdmmc->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a long response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (four words) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - (void)sdcp; - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_WAITRESP_1 | - SDMMC_CMD_CPSMEN; - while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL)) == 0) - ; - sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL); - if ((sta & (SDMMC_STA_ERROR_MASK)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - /* Save bytes in reverse order because MSB in response comes first.*/ - *resp++ = sdcp->sdmmc->RESP4; - *resp++ = sdcp->sdmmc->RESP3; - *resp++ = sdcp->sdmmc->RESP2; - *resp = sdcp->sdmmc->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Reads special registers using data bus. - * @details Needs only during card detection procedure. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] buf pointer to the read buffer - * @param[in] bytes number of bytes to read - * @param[in] cmd card command - * @param[in] arg argument for command - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, - uint8_t cmd, uint32_t arg) { - uint32_t resp[1]; - - if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes)) - goto error; - - if (sdc_lld_send_cmd_short_crc(sdcp, cmd, arg, resp) - || MMCSD_R1_ERROR(resp[0])) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, 1, resp)) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, 1, resp); - return HAL_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] blocks number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks) { - uint32_t resp[1]; - - osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); - - sdcp->sdmmc->DTIMER = sdcp->rtmo; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, - (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | - SDMMC_MASK_DTIMEOUTIE | - SDMMC_MASK_RXOVERRIE | - SDMMC_MASK_DATAENDIE; - sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; - - /* Transaction starts just after DTEN bit setting.*/ - sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | - SDMMC_DCTRL_DBLOCKSIZE_3 | - SDMMC_DCTRL_DBLOCKSIZE_0 | - SDMMC_DCTRL_DMAEN | - SDMMC_DCTRL_DTEN; - - if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, blocks, resp); - return HAL_FAILED; -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks) { - uint32_t resp[1]; - - osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); - - sdcp->sdmmc->DTIMER = sdcp->wtmo; - - /* Checks for errors and waits for the card to be ready for writing.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, - (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | - SDMMC_MASK_DTIMEOUTIE | - SDMMC_MASK_TXUNDERRIE | - SDMMC_MASK_DATAENDIE; - sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; - - /* Talk to card what we want from it.*/ - if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true) - goto error; - - /* Transaction starts just after DTEN bit setting.*/ - sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DBLOCKSIZE_3 | - SDMMC_DCTRL_DBLOCKSIZE_0 | - SDMMC_DCTRL_DMAEN | - SDMMC_DCTRL_DTEN; - - if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, blocks, resp); - return HAL_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] blocks number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks) { - -#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < blocks; i++) { - if (sdc_lld_read_aligned(sdcp, startblk, sdcp->buf, 1)) - return HAL_FAILED; - memcpy(buf, sdcp->buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - startblk++; - } - return HAL_SUCCESS; - } -#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); -#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_read_aligned(sdcp, startblk, buf, blocks); -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] blocks number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks) { - -#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < blocks; i++) { - memcpy(sdcp->buf, buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - if (sdc_lld_write_aligned(sdcp, startblk, sdcp->buf, 1)) - return HAL_FAILED; - startblk++; - } - return HAL_SUCCESS; - } -#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); -#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_write_aligned(sdcp, startblk, buf, blocks); -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool sdc_lld_sync(SDCDriver *sdcp) { - - /* CHTODO: Implement.*/ - (void)sdcp; - return HAL_SUCCESS; -} - -#endif /* HAL_USE_SDC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SDMMCv1/hal_sdc_lld.c + * @brief STM32 SDC subsystem low level driver source. + * + * @addtogroup SDC + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SDMMC_ICR_ALL_FLAGS \ + (SDMMC_ICR_CCRCFAILC | SDMMC_ICR_DCRCFAILC | \ + SDMMC_ICR_CTIMEOUTC | SDMMC_ICR_DTIMEOUTC | \ + SDMMC_ICR_TXUNDERRC | SDMMC_ICR_RXOVERRC | \ + SDMMC_ICR_CMDRENDC | SDMMC_ICR_CMDSENTC | \ + SDMMC_ICR_DATAENDC | SDMMC_ICR_DBCKENDC | \ + SDMMC_ICR_SDIOITC) + +#define SDMMC_STA_ERROR_MASK \ + (SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | \ + SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | \ + SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR) + +#define SDMMC_CLKDIV_HS (2 - 2) +#define SDMMC_CLKDIV_LS (120 - 2) + +#define SDMMC1_WRITE_TIMEOUT \ + (((STM32_SDMMC1CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ + STM32_SDC_SDMMC_WRITE_TIMEOUT) +#define SDMMC1_READ_TIMEOUT \ + (((STM32_SDMMC1CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ + STM32_SDC_SDMMC_READ_TIMEOUT) + +#define SDMMC2_WRITE_TIMEOUT \ + (((STM32_SDMMC2CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ + STM32_SDC_SDMMC_WRITE_TIMEOUT) +#define SDMMC2_READ_TIMEOUT \ + (((STM32_SDMMC2CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \ + STM32_SDC_SDMMC_READ_TIMEOUT) + +#define SDMMC1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SDC_SDMMC1_DMA_STREAM, \ + STM32_SDC_SDMMC1_DMA_CHN) + +#define SDMMC2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SDC_SDMMC2_DMA_STREAM, \ + STM32_SDC_SDMMC2_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SDCD1 driver identifier.*/ +#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__) +SDCDriver SDCD1; +#endif + +/** @brief SDCD2 driver identifier.*/ +#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__) +SDCDriver SDCD2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief SDIO default configuration. + */ +static const SDCConfig sdc_default_cfg = { + SDC_MODE_4BIT +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Prepares to handle read transaction. + * @details Designed for read special registers from card. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] buf pointer to the read buffer + * @param[in] bytes number of bytes to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp, + uint8_t *buf, uint32_t bytes) { + osalDbgCheck(bytes < 0x1000000); + + sdcp->sdmmc->DTIMER = sdcp->rtmo; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, bytes / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | + SDMMC_MASK_DTIMEOUTIE | + SDMMC_MASK_RXOVERRIE | + SDMMC_MASK_DATAENDIE; + sdcp->sdmmc->DLEN = bytes; + + /* Transaction starts just after DTEN bit setting.*/ + sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | + SDMMC_DCTRL_DTMODE | /* Multibyte data transfer.*/ + SDMMC_DCTRL_DMAEN | + SDMMC_DCTRL_DTEN; + + return HAL_SUCCESS; +} + +/** + * @brief Prepares card to handle read transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to read + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Send read multiple blocks command to card.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + else { + /* Send read single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Prepares card to handle write transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to write + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Write multiple blocks command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + else { + /* Write single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Wait end of data transaction and performs finalizations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + */ +static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, + uint32_t *resp) { + + /* Note the mask is checked before going to sleep because the interrupt + may have occurred before reaching the critical zone.*/ + osalSysLock(); + if (sdcp->sdmmc->MASK != 0) + osalThreadSuspendS(&sdcp->thread); + if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) { + osalSysUnlock(); + return HAL_FAILED; + } + + /* Waits for transfer completion at DMA level, then the stream is + disabled and cleared.*/ + dmaWaitCompletion(sdcp->dma); + + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->DCTRL = 0; + osalSysUnlock(); + + /* Finalize transaction.*/ + if (n > 1) + return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); + + return HAL_SUCCESS; +} + +/** + * @brief Gets SDC errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] sta value of the STA register + * + * @notapi + */ +static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { + uint32_t errors = SDC_NO_ERROR; + + if (sta & SDMMC_STA_CCRCFAIL) + errors |= SDC_CMD_CRC_ERROR; + if (sta & SDMMC_STA_DCRCFAIL) + errors |= SDC_DATA_CRC_ERROR; + if (sta & SDMMC_STA_CTIMEOUT) + errors |= SDC_COMMAND_TIMEOUT; + if (sta & SDMMC_STA_DTIMEOUT) + errors |= SDC_DATA_TIMEOUT; + if (sta & SDMMC_STA_TXUNDERR) + errors |= SDC_TX_UNDERRUN; + if (sta & SDMMC_STA_RXOVERR) + errors |= SDC_RX_OVERRUN; +/* if (sta & SDMMC_STA_STBITERR) + errors |= SDC_STARTBIT_ERROR;*/ + + sdcp->errors |= errors; +} + +/** + * @brief Performs clean transaction stopping in case of errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @notapi + */ +static void sdc_lld_error_cleanup(SDCDriver *sdcp, + uint32_t n, + uint32_t *resp) { + uint32_t sta = sdcp->sdmmc->STA; + + dmaStreamDisable(sdcp->dma); + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = 0; + sdcp->sdmmc->DCTRL = 0; + sdc_lld_collect_errors(sdcp, sta); + + if (n > 1) + sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief SDMMC1 IRQ handler. + * @details It just wakes transaction thread, errors handling is performed in + * there. + * + * @isr + */ +#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(STM32_SDMMC1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + + /* Disables the source but the status flags are not reset because the + read/write functions needs to check them.*/ + SDMMC1->MASK = 0; + + osalThreadResumeI(&SDCD1.thread, MSG_OK); + + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/** + * @brief SDMMC2 IRQ handler. + * @details It just wakes transaction thread, errors handling is performed in + * there. + * + * @isr + */ +#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(STM32_SDMMC2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + + /* Disables the source but the status flags are not reset because the + read/write functions needs to check them.*/ + SDMMC2->MASK = 0; + + osalThreadResumeI(&SDCD2.thread, MSG_OK); + + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SDC driver initialization. + * + * @notapi + */ +void sdc_lld_init(void) { + +#if STM32_SDC_USE_SDMMC1 + sdcObjectInit(&SDCD1); + SDCD1.thread = NULL; + SDCD1.rtmo = SDMMC1_READ_TIMEOUT; + SDCD1.wtmo = SDMMC1_WRITE_TIMEOUT; + SDCD1.dma = NULL; + SDCD1.sdmmc = SDMMC1; + nvicEnableVector(STM32_SDMMC1_NUMBER, STM32_SDC_SDMMC1_IRQ_PRIORITY); +#endif + +#if STM32_SDC_USE_SDMMC2 + sdcObjectInit(&SDCD2); + SDCD2.thread = NULL; + SDCD2.rtmo = SDMMC2_READ_TIMEOUT; + SDCD2.wtmo = SDMMC2_WRITE_TIMEOUT; + SDCD2.dma = NULL; + SDCD2.sdmmc = SDMMC2; + nvicEnableVector(STM32_SDMMC2_NUMBER, STM32_SDC_SDMMC2_IRQ_PRIORITY); +#endif +} + +/** + * @brief Configures and activates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start(SDCDriver *sdcp) { + + /* Checking configuration, using a default if NULL has been passed.*/ + if (sdcp->config == NULL) { + sdcp->config = &sdc_default_cfg; + } + + sdcp->dmamode = STM32_DMA_CR_PSIZE_WORD | + STM32_DMA_CR_MSIZE_WORD | + STM32_DMA_CR_MINC; + +#if STM32_DMA_ADVANCED + sdcp->dmamode |= STM32_DMA_CR_PFCTRL | + STM32_DMA_CR_PBURST_INCR4 | + STM32_DMA_CR_MBURST_INCR4; +#endif + + /* If in stopped state then clocks are enabled and DMA initialized.*/ + if (sdcp->state == BLK_STOP) { +#if STM32_SDC_USE_SDMMC1 + if (&SDCD1 == sdcp) { + sdcp->dma = dmaStreamAllocI(STM32_SDC_SDMMC1_DMA_STREAM, + STM32_SDC_SDMMC1_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream"); + + sdcp->dmamode |= STM32_DMA_CR_CHSEL(SDMMC1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SDC_SDMMC1_DMA_PRIORITY); + dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdmmc->FIFO); +#if STM32_DMA_ADVANCED + dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | + STM32_DMA_FCR_FTH_FULL); +#endif + rccEnableSDMMC1(true); + } +#endif /* STM32_SDC_USE_SDMMC1 */ + +#if STM32_SDC_USE_SDMMC2 + if (&SDCD2 == sdcp) { + sdcp->dma = dmaStreamAllocI(STM32_SDC_SDMMC2_DMA_STREAM, + STM32_SDC_SDMMC2_IRQ_PRIORITY, + NULL, + NULL); + osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream"); + + sdcp->dmamode |= STM32_DMA_CR_CHSEL(SDMMC2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SDC_SDMMC2_DMA_PRIORITY); + dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdmmc->FIFO); +#if STM32_DMA_ADVANCED + dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | + STM32_DMA_FCR_FTH_FULL); +#endif + rccEnableSDMMC2(true); + } +#endif /* STM32_SDC_USE_SDMMC2 */ + } + + /* Configuration, card clock is initially stopped.*/ + sdcp->sdmmc->POWER = 0; + sdcp->sdmmc->CLKCR = 0; + sdcp->sdmmc->DCTRL = 0; + sdcp->sdmmc->DTIMER = 0; +} + +/** + * @brief Deactivates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop(SDCDriver *sdcp) { + + if (sdcp->state != BLK_STOP) { + + /* SDIO deactivation.*/ + sdcp->sdmmc->POWER = 0; + sdcp->sdmmc->CLKCR = 0; + sdcp->sdmmc->DCTRL = 0; + sdcp->sdmmc->DTIMER = 0; + + /* DMA stream released.*/ + dmaStreamFreeI(sdcp->dma); + sdcp->dma = NULL; + + /* Clock deactivation.*/ +#if STM32_SDC_USE_SDMMC1 + if (&SDCD1 == sdcp) { + rccDisableSDMMC1(); + } +#endif + +#if STM32_SDC_USE_SDMMC2 + if (&SDCD2 == sdcp) { + rccDisableSDMMC2(); + } +#endif + } +} + +/** + * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start_clk(SDCDriver *sdcp) { + + /* Initial clock setting: 400kHz, 1bit mode.*/ + sdcp->sdmmc->CLKCR = SDMMC_CLKDIV_LS; + sdcp->sdmmc->POWER |= SDMMC_POWER_PWRCTRL_0 | SDMMC_POWER_PWRCTRL_1; + sdcp->sdmmc->CLKCR |= SDMMC_CLKCR_CLKEN; + + /* Clock activation delay.*/ + osalThreadSleep(OSAL_MS2I(STM32_SDC_SDMMC_CLOCK_DELAY)); +} + +/** + * @brief Sets the SDIO clock to data mode (25/50 MHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] clk the clock mode + * + * @notapi + */ +void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) { + +#if STM32_SDC_SDMMC_50MHZ + if (SDC_CLK_50MHz == clk) { + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | +#if STM32_SDC_SDMMC_PWRSAV + SDMMC_CLKDIV_HS | SDMMC_CLKCR_BYPASS | + SDMMC_CLKCR_PWRSAV; +#else + SDMMC_CLKDIV_HS | SDMMC_CLKCR_BYPASS; +#endif + } + else { +#if STM32_SDC_SDMMC_PWRSAV + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS | + SDMMC_CLKCR_PWRSAV; +#else + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS; +#endif + } +#else + (void)clk; + +#if STM32_SDC_SDMMC_PWRSAV + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS | + SDMMC_CLKCR_PWRSAV; +#else + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS; +#endif +#endif +} + +/** + * @brief Stops the SDIO clock. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop_clk(SDCDriver *sdcp) { + + sdcp->sdmmc->CLKCR = 0; + sdcp->sdmmc->POWER = 0; +} + +/** + * @brief Switches the bus to 1, 4 or 8 bits mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] mode bus mode + * + * @notapi + */ +void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { + uint32_t clk = sdcp->sdmmc->CLKCR & ~SDMMC_CLKCR_WIDBUS; + + switch (mode) { + case SDC_MODE_1BIT: + sdcp->sdmmc->CLKCR = clk; + break; + case SDC_MODE_4BIT: + sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_0; + break; + case SDC_MODE_8BIT: + sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_1; + break; + } +} + +/** + * @brief Sends an SDIO command with no response expected. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * + * @notapi + */ +void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_CPSMEN; + while ((sdcp->sdmmc->STA & SDMMC_STA_CMDSENT) == 0) + ; + sdcp->sdmmc->ICR = SDMMC_ICR_CMDSENTC; +} + +/** + * @brief Sends an SDIO command with a short response expected. + * @note The CRC is not verified. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; + while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL)) == 0) + ; + sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL); + if ((sta & (SDMMC_STA_CTIMEOUT)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + *resp = sdcp->sdmmc->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a short response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; + while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL)) == 0) + ; + sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL); + if ((sta & (SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + *resp = sdcp->sdmmc->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a long response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (four words) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + (void)sdcp; + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_WAITRESP_1 | + SDMMC_CMD_CPSMEN; + while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL)) == 0) + ; + sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL); + if ((sta & (SDMMC_STA_ERROR_MASK)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + /* Save bytes in reverse order because MSB in response comes first.*/ + *resp++ = sdcp->sdmmc->RESP4; + *resp++ = sdcp->sdmmc->RESP3; + *resp++ = sdcp->sdmmc->RESP2; + *resp = sdcp->sdmmc->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Reads special registers using data bus. + * @details Needs only during card detection procedure. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] buf pointer to the read buffer + * @param[in] bytes number of bytes to read + * @param[in] cmd card command + * @param[in] arg argument for command + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, + uint8_t cmd, uint32_t arg) { + uint32_t resp[1]; + + if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes)) + goto error; + + if (sdc_lld_send_cmd_short_crc(sdcp, cmd, arg, resp) + || MMCSD_R1_ERROR(resp[0])) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, 1, resp)) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, 1, resp); + return HAL_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] blocks number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks) { + uint32_t resp[1]; + + osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); + + sdcp->sdmmc->DTIMER = sdcp->rtmo; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, + (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | + SDMMC_MASK_DTIMEOUTIE | + SDMMC_MASK_RXOVERRIE | + SDMMC_MASK_DATAENDIE; + sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; + + /* Transaction starts just after DTEN bit setting.*/ + sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | + SDMMC_DCTRL_DBLOCKSIZE_3 | + SDMMC_DCTRL_DBLOCKSIZE_0 | + SDMMC_DCTRL_DMAEN | + SDMMC_DCTRL_DTEN; + + if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, blocks, resp); + return HAL_FAILED; +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks) { + uint32_t resp[1]; + + osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); + + sdcp->sdmmc->DTIMER = sdcp->wtmo; + + /* Checks for errors and waits for the card to be ready for writing.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, + (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | + SDMMC_MASK_DTIMEOUTIE | + SDMMC_MASK_TXUNDERRIE | + SDMMC_MASK_DATAENDIE; + sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; + + /* Talk to card what we want from it.*/ + if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true) + goto error; + + /* Transaction starts just after DTEN bit setting.*/ + sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DBLOCKSIZE_3 | + SDMMC_DCTRL_DBLOCKSIZE_0 | + SDMMC_DCTRL_DMAEN | + SDMMC_DCTRL_DTEN; + + if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, blocks, resp); + return HAL_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] blocks number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks) { + +#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < blocks; i++) { + if (sdc_lld_read_aligned(sdcp, startblk, sdcp->buf, 1)) + return HAL_FAILED; + memcpy(buf, sdcp->buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + startblk++; + } + return HAL_SUCCESS; + } +#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); +#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_read_aligned(sdcp, startblk, buf, blocks); +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] blocks number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks) { + +#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < blocks; i++) { + memcpy(sdcp->buf, buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + if (sdc_lld_write_aligned(sdcp, startblk, sdcp->buf, 1)) + return HAL_FAILED; + startblk++; + } + return HAL_SUCCESS; + } +#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); +#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_write_aligned(sdcp, startblk, buf, blocks); +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdc_lld_sync(SDCDriver *sdcp) { + + /* CHTODO: Implement.*/ + (void)sdcp; + return HAL_SUCCESS; +} + +#endif /* HAL_USE_SDC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h b/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h index b9ad69c715..77353f519e 100644 --- a/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h +++ b/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h @@ -1,400 +1,400 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SDMMCv1/hal_sdc_lld.h - * @brief STM32 SDC subsystem low level driver header. - * - * @addtogroup SDC - * @{ - */ - -#ifndef HAL_SDC_LLD_H -#define HAL_SDC_LLD_H - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SDMMC1 driver enable switch. - * @details If set to @p TRUE the support for SDMMC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SDC_USE_SDMMC1) || defined(__DOXYGEN__) -#define STM32_SDC_USE_SDMMC1 FALSE -#endif - -/** - * @brief SDMMC2 driver enable switch. - * @details If set to @p TRUE the support for SDMMC2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SDC_USE_SDMMC2) || defined(__DOXYGEN__) -#define STM32_SDC_USE_SDMMC2 FALSE -#endif - -/** - * @brief Support for unaligned transfers. - * @note Unaligned transfers are much slower. - */ -#if !defined(STM32_SDC_SDMMC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE -#endif - -/** - * @brief Enable clock bypass. - * @note Allow clock speed up to 50 Mhz. - */ -#if !defined(STM32_SDC_SDMMC_50MHZ) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_50MHZ FALSE -#endif - -/** - * @brief Write timeout in milliseconds. - */ -#if !defined(STM32_SDC_SDMMC_WRITE_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 -#endif - -/** - * @brief Read timeout in milliseconds. - */ -#if !defined(STM32_SDC_SDMMC_READ_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 -#endif - -/** - * @brief Card clock activation delay in milliseconds. - */ -#if !defined(STM32_SDC_SDMMC_CLOCK_DELAY) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_CLOCK_DELAY 10 -#endif - -/** - * @brief Card clock power saving enable. - */ -#if !defined(STM32_SDC_SDMMC_PWRSAV) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_PWRSAV TRUE -#endif - -/** - * @brief SDMMC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_SDC_SDMMC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 -#endif - -/** - * @brief SDMMC2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_SDC_SDMMC2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC2_DMA_PRIORITY 3 -#endif - -/** - * @brief SDMMC1 interrupt priority level setting. - */ -#if !defined(STM32_SDC_SDMMC1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 -#endif - -/** - * @brief SDMMC2 interrupt priority level setting. - */ -#if !defined(STM32_SDC_SDMMC2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC2_IRQ_PRIORITY 9 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Registry checks.*/ -#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_HANDLER)) || \ - (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_HANDLER)) -#error "STM32_SDMMCx_HANDLER not defined in registry" -#endif - -#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_NUMBER)) || \ - (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_NUMBER)) -#error "STM32_SDMMCx_NUMBER not defined in registry" -#endif - -#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_MSK)) || \ - (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_MSK)) -#error "STM32_SDC_SDMMCx_DMA_MSK not defined in registry" -#endif - -#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_CHN)) || \ - (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_CHN)) -#error "STM32_SDC_SDMMCx_DMA_CHN not defined in registry" -#endif - -/* Units checks.*/ -#if STM32_SDC_USE_SDMMC1 && !STM32_HAS_SDMMC1 -#error "SDMMC1 not present in the selected device" -#endif - -#if STM32_SDC_USE_SDMMC2 && !STM32_HAS_SDMMC2 -#error "SDMMC2 not present in the selected device" -#endif - -#if !STM32_SDC_USE_SDMMC1 && !STM32_SDC_USE_SDMMC2 -#error "SDC driver activated but no SDMMC peripheral assigned" -#endif - -/* Clock related tests.*/ -#if STM32_HAS_SDMMC1 && !defined(STM32_SDMMC1CLK) -#error "STM32_SDMMC1CLK not defined" -#endif - -/* Clock related tests.*/ -#if STM32_HAS_SDMMC2 && !defined(STM32_SDMMC2CLK) -#error "STM32_SDMMC2CLK not defined" -#endif - -#if !defined(STM32_HCLK) -#error "STM32_HCLK not defined" -#endif - -#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK * 10 > STM32_HCLK * 7) -#error "STM32_SDMMC1CLK must not exceed STM32_HCLK * 0.7" -#endif - -#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK * 10 > STM32_HCLK * 7) -#error "STM32_SDMMC2CLK must not exceed STM32_HCLK * 0.7" -#endif - -#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK > 48000000) -#error "STM32_SDMMC1CLK must not exceed 48MHz" -#endif - -#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK > 48000000) -#error "STM32_SDMMC2CLK must not exceed 48MHz" -#endif - -#if defined(STM32_SDC_SDMMC_50MHZ) && STM32_SDC_SDMMC_50MHZ && !defined(STM32F7XX) -#error "50 Mhz clock only works for STM32F7XX" -#endif - -/* SDMMC IRQ priority tests.*/ -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDMMC1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDMMC1" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDMMC2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDMMC2" -#endif - -/* DMA priority tests.*/ -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDMMC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDMMC1" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDMMC2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDMMC2" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_STREAM) -#error "SDMMC1 DMA streams not defined" -#endif - -#if STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_STREAM) -#error "SDMMC2 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_SDC_USE_SDMMC1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SDC_SDMMC1_DMA_STREAM, STM32_SDC_SDMMC1_DMA_MSK) -#error "invalid DMA stream associated to SDMMC1" -#endif - -#if STM32_SDC_USE_SDMMC2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SDC_SDMMC2_DMA_STREAM, STM32_SDC_SDMMC2_DMA_MSK) -#error "invalid DMA stream associated to SDMMC2" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of card flags. - */ -typedef uint32_t sdcmode_t; - -/** - * @brief SDC Driver condition flags type. - */ -typedef uint32_t sdcflags_t; - -/** - * @brief Type of a structure representing an SDC driver. - */ -typedef struct SDCDriver SDCDriver; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Bus width. - */ - sdcbusmode_t bus_width; - /* End of the mandatory fields.*/ -} SDCConfig; - -/** - * @brief @p SDCDriver specific methods. - */ -#define _sdc_driver_methods \ - _mmcsd_block_device_methods - -/** - * @extends MMCSDBlockDeviceVMT - * - * @brief @p SDCDriver virtual methods table. - */ -struct SDCDriverVMT { - _sdc_driver_methods -}; - -/** - * @brief Structure representing an SDC driver. - */ -struct SDCDriver { - /** - * @brief Virtual Methods Table. - */ - const struct SDCDriverVMT *vmt; - _mmcsd_block_device_data - /** - * @brief Current configuration data. - */ - const SDCConfig *config; - /** - * @brief Various flags regarding the mounted card. - */ - sdcmode_t cardmode; - /** - * @brief Errors flags. - */ - sdcflags_t errors; - /** - * @brief Card RCA. - */ - uint32_t rca; - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion IRQ. - */ - thread_reference_t thread; - /** - * @brief DTIMER register value for read operations. - */ - uint32_t rtmo; - /** - * @brief DTIMER register value for write operations. - */ - uint32_t wtmo; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dma; - /** - * @brief Pointer to the SDMMC registers block. - * @note Needed for debugging aid. - */ - SDMMC_TypeDef *sdmmc; - /** - * @brief Buffer for internal operations. - */ - uint8_t buf[MMCSD_BLOCK_SIZE]; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SDC_USE_SDMMC1 && !defined(__DOXYGEN__) -extern SDCDriver SDCD1; -#endif - -#if STM32_SDC_USE_SDMMC2 && !defined(__DOXYGEN__) -extern SDCDriver SDCD2; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sdc_lld_init(void); - void sdc_lld_start(SDCDriver *sdcp); - void sdc_lld_stop(SDCDriver *sdcp); - void sdc_lld_start_clk(SDCDriver *sdcp); - void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk); - void sdc_lld_stop_clk(SDCDriver *sdcp); - void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); - void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); - bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, - uint8_t cmd, uint32_t argument); - bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks); - bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks); - bool sdc_lld_sync(SDCDriver *sdcp); - bool sdc_lld_is_card_inserted(SDCDriver *sdcp); - bool sdc_lld_is_write_protected(SDCDriver *sdcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SDC */ - -#endif /* HAL_SDC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SDMMCv1/hal_sdc_lld.h + * @brief STM32 SDC subsystem low level driver header. + * + * @addtogroup SDC + * @{ + */ + +#ifndef HAL_SDC_LLD_H +#define HAL_SDC_LLD_H + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SDMMC1 driver enable switch. + * @details If set to @p TRUE the support for SDMMC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SDC_USE_SDMMC1) || defined(__DOXYGEN__) +#define STM32_SDC_USE_SDMMC1 FALSE +#endif + +/** + * @brief SDMMC2 driver enable switch. + * @details If set to @p TRUE the support for SDMMC2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SDC_USE_SDMMC2) || defined(__DOXYGEN__) +#define STM32_SDC_USE_SDMMC2 FALSE +#endif + +/** + * @brief Support for unaligned transfers. + * @note Unaligned transfers are much slower. + */ +#if !defined(STM32_SDC_SDMMC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#endif + +/** + * @brief Enable clock bypass. + * @note Allow clock speed up to 50 Mhz. + */ +#if !defined(STM32_SDC_SDMMC_50MHZ) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_50MHZ FALSE +#endif + +/** + * @brief Write timeout in milliseconds. + */ +#if !defined(STM32_SDC_SDMMC_WRITE_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#endif + +/** + * @brief Read timeout in milliseconds. + */ +#if !defined(STM32_SDC_SDMMC_READ_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#endif + +/** + * @brief Card clock activation delay in milliseconds. + */ +#if !defined(STM32_SDC_SDMMC_CLOCK_DELAY) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#endif + +/** + * @brief Card clock power saving enable. + */ +#if !defined(STM32_SDC_SDMMC_PWRSAV) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_PWRSAV TRUE +#endif + +/** + * @brief SDMMC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_SDC_SDMMC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#endif + +/** + * @brief SDMMC2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_SDC_SDMMC2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC2_DMA_PRIORITY 3 +#endif + +/** + * @brief SDMMC1 interrupt priority level setting. + */ +#if !defined(STM32_SDC_SDMMC1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 +#endif + +/** + * @brief SDMMC2 interrupt priority level setting. + */ +#if !defined(STM32_SDC_SDMMC2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC2_IRQ_PRIORITY 9 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks.*/ +#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_HANDLER)) || \ + (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_HANDLER)) +#error "STM32_SDMMCx_HANDLER not defined in registry" +#endif + +#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_NUMBER)) || \ + (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_NUMBER)) +#error "STM32_SDMMCx_NUMBER not defined in registry" +#endif + +#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_MSK)) || \ + (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_MSK)) +#error "STM32_SDC_SDMMCx_DMA_MSK not defined in registry" +#endif + +#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_CHN)) || \ + (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_CHN)) +#error "STM32_SDC_SDMMCx_DMA_CHN not defined in registry" +#endif + +/* Units checks.*/ +#if STM32_SDC_USE_SDMMC1 && !STM32_HAS_SDMMC1 +#error "SDMMC1 not present in the selected device" +#endif + +#if STM32_SDC_USE_SDMMC2 && !STM32_HAS_SDMMC2 +#error "SDMMC2 not present in the selected device" +#endif + +#if !STM32_SDC_USE_SDMMC1 && !STM32_SDC_USE_SDMMC2 +#error "SDC driver activated but no SDMMC peripheral assigned" +#endif + +/* Clock related tests.*/ +#if STM32_HAS_SDMMC1 && !defined(STM32_SDMMC1CLK) +#error "STM32_SDMMC1CLK not defined" +#endif + +/* Clock related tests.*/ +#if STM32_HAS_SDMMC2 && !defined(STM32_SDMMC2CLK) +#error "STM32_SDMMC2CLK not defined" +#endif + +#if !defined(STM32_HCLK) +#error "STM32_HCLK not defined" +#endif + +#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK * 10 > STM32_HCLK * 7) +#error "STM32_SDMMC1CLK must not exceed STM32_HCLK * 0.7" +#endif + +#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK * 10 > STM32_HCLK * 7) +#error "STM32_SDMMC2CLK must not exceed STM32_HCLK * 0.7" +#endif + +#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK > 48000000) +#error "STM32_SDMMC1CLK must not exceed 48MHz" +#endif + +#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK > 48000000) +#error "STM32_SDMMC2CLK must not exceed 48MHz" +#endif + +#if defined(STM32_SDC_SDMMC_50MHZ) && STM32_SDC_SDMMC_50MHZ && !defined(STM32F7XX) +#error "50 Mhz clock only works for STM32F7XX" +#endif + +/* SDMMC IRQ priority tests.*/ +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDMMC1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDMMC1" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDMMC2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDMMC2" +#endif + +/* DMA priority tests.*/ +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDMMC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDMMC1" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDMMC2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDMMC2" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_STREAM) +#error "SDMMC1 DMA streams not defined" +#endif + +#if STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_STREAM) +#error "SDMMC2 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SDC_USE_SDMMC1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SDC_SDMMC1_DMA_STREAM, STM32_SDC_SDMMC1_DMA_MSK) +#error "invalid DMA stream associated to SDMMC1" +#endif + +#if STM32_SDC_USE_SDMMC2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SDC_SDMMC2_DMA_STREAM, STM32_SDC_SDMMC2_DMA_MSK) +#error "invalid DMA stream associated to SDMMC2" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of card flags. + */ +typedef uint32_t sdcmode_t; + +/** + * @brief SDC Driver condition flags type. + */ +typedef uint32_t sdcflags_t; + +/** + * @brief Type of a structure representing an SDC driver. + */ +typedef struct SDCDriver SDCDriver; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Bus width. + */ + sdcbusmode_t bus_width; + /* End of the mandatory fields.*/ +} SDCConfig; + +/** + * @brief @p SDCDriver specific methods. + */ +#define _sdc_driver_methods \ + _mmcsd_block_device_methods + +/** + * @extends MMCSDBlockDeviceVMT + * + * @brief @p SDCDriver virtual methods table. + */ +struct SDCDriverVMT { + _sdc_driver_methods +}; + +/** + * @brief Structure representing an SDC driver. + */ +struct SDCDriver { + /** + * @brief Virtual Methods Table. + */ + const struct SDCDriverVMT *vmt; + _mmcsd_block_device_data + /** + * @brief Current configuration data. + */ + const SDCConfig *config; + /** + * @brief Various flags regarding the mounted card. + */ + sdcmode_t cardmode; + /** + * @brief Errors flags. + */ + sdcflags_t errors; + /** + * @brief Card RCA. + */ + uint32_t rca; + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion IRQ. + */ + thread_reference_t thread; + /** + * @brief DTIMER register value for read operations. + */ + uint32_t rtmo; + /** + * @brief DTIMER register value for write operations. + */ + uint32_t wtmo; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dma; + /** + * @brief Pointer to the SDMMC registers block. + * @note Needed for debugging aid. + */ + SDMMC_TypeDef *sdmmc; + /** + * @brief Buffer for internal operations. + */ + uint8_t buf[MMCSD_BLOCK_SIZE]; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SDC_USE_SDMMC1 && !defined(__DOXYGEN__) +extern SDCDriver SDCD1; +#endif + +#if STM32_SDC_USE_SDMMC2 && !defined(__DOXYGEN__) +extern SDCDriver SDCD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sdc_lld_init(void); + void sdc_lld_start(SDCDriver *sdcp); + void sdc_lld_stop(SDCDriver *sdcp); + void sdc_lld_start_clk(SDCDriver *sdcp); + void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk); + void sdc_lld_stop_clk(SDCDriver *sdcp); + void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); + void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); + bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, + uint8_t cmd, uint32_t argument); + bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks); + bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks); + bool sdc_lld_sync(SDCDriver *sdcp); + bool sdc_lld_is_card_inserted(SDCDriver *sdcp); + bool sdc_lld_is_write_protected(SDCDriver *sdcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SDC */ + +#endif /* HAL_SDC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk b/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk index cf8b9d20e8..774cca9246 100644 --- a/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk +++ b/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2 diff --git a/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c b/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c index 79701e04ca..bbdd07f135 100644 --- a/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c +++ b/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c @@ -1,865 +1,865 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SDMMCv2/hal_sdc_lld.c - * @brief STM32 SDC subsystem low level driver source. - * - * @addtogroup SDC - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SDMMC_ICR_ALL_FLAGS 0xFFFFFFFFU - -#define SDMMC_STA_ERROR_MASK \ - (SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | \ - SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | \ - SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SDCD1 driver identifier.*/ -#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__) -SDCDriver SDCD1; -#endif - -/** @brief SDCD2 driver identifier.*/ -#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__) -SDCDriver SDCD2; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief SDIO default configuration. - */ -static const SDCConfig sdc_default_cfg = { - SDC_MODE_4BIT -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Calculates a clock divider for the specified frequency. - * @note The divider is calculated to not exceed the required frequency - * in case of non-integer division. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] f required frequency - */ -static uint32_t sdc_lld_clkdiv(SDCDriver *sdcp, uint32_t f) { - - if (f >= sdcp->clkfreq) { - return 0; - } - - return (sdcp->clkfreq + (f * 2) - 1) / (f * 2); -} - -/** - * @brief Prepares to handle read transaction. - * @details Designed for read special registers from card. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] buf pointer to the read buffer - * @param[in] bytes number of bytes to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp, - uint8_t *buf, uint32_t bytes) { - osalDbgCheck(bytes < 0x1000000); - - sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_READ_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Setting up data transfer.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | - SDMMC_MASK_DTIMEOUTIE | - SDMMC_MASK_RXOVERRIE | - SDMMC_MASK_DATAENDIE; - sdcp->sdmmc->DLEN = bytes; - - /* Transfer modes.*/ - sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | - SDMMC_DCTRL_DTMODE_0; /* Multibyte data transfer.*/ - - /* Prepares IDMA.*/ - sdcp->sdmmc->IDMABASE0 = (uint32_t)buf; - sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN; - - return HAL_SUCCESS; -} - -/** - * @brief Prepares card to handle read transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to read - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Send read multiple blocks command to card.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_READ_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - else { - /* Send read single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_READ_SINGLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Prepares card to handle write transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to write - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Write multiple blocks command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - else { - /* Write single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_WRITE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Wait end of data transaction and performs finalizations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - */ -static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, - uint32_t *resp) { - - /* Note the mask is checked before going to sleep because the interrupt - may have occurred before reaching the critical zone.*/ - osalSysLock(); - if (sdcp->sdmmc->MASK != 0) - osalThreadSuspendS(&sdcp->thread); - - /* Stopping operations.*/ - sdcp->sdmmc->IDMACTRL = 0; - sdcp->sdmmc->MASK = 0; - sdcp->sdmmc->DCTRL = 0; - - if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) { - osalSysUnlock(); - return HAL_FAILED; - } - - /* Clearing status.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - osalSysUnlock(); - - /* Finalize transaction.*/ - if (n > 1) - return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); - - return HAL_SUCCESS; -} - -/** - * @brief Gets SDC errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] sta value of the STA register - * - * @notapi - */ -static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { - uint32_t errors = SDC_NO_ERROR; - - if (sta & SDMMC_STA_CCRCFAIL) - errors |= SDC_CMD_CRC_ERROR; - if (sta & SDMMC_STA_DCRCFAIL) - errors |= SDC_DATA_CRC_ERROR; - if (sta & SDMMC_STA_CTIMEOUT) - errors |= SDC_COMMAND_TIMEOUT; - if (sta & SDMMC_STA_DTIMEOUT) - errors |= SDC_DATA_TIMEOUT; - if (sta & SDMMC_STA_TXUNDERR) - errors |= SDC_TX_UNDERRUN; - if (sta & SDMMC_STA_RXOVERR) - errors |= SDC_RX_OVERRUN; -/* if (sta & SDMMC_STA_STBITERR) - errors |= SDC_STARTBIT_ERROR;*/ - - sdcp->errors |= errors; -} - -/** - * @brief Performs clean transaction stopping in case of errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @notapi - */ -static void sdc_lld_error_cleanup(SDCDriver *sdcp, - uint32_t n, - uint32_t *resp) { - uint32_t sta = sdcp->sdmmc->STA; - - /* Clearing status.*/ - sta = sdcp->sdmmc->STA; - sdcp->sdmmc->ICR = sta; - sdc_lld_collect_errors(sdcp, sta); - - if (n > 1) - sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SDC driver initialization. - * - * @notapi - */ -void sdc_lld_init(void) { - -#if STM32_SDC_USE_SDMMC1 - sdcObjectInit(&SDCD1); - SDCD1.thread = NULL; - SDCD1.sdmmc = SDMMC1; - SDCD1.clkfreq = STM32_SDMMC1CLK; -#endif - -#if STM32_SDC_USE_SDMMC2 - sdcObjectInit(&SDCD2); - SDCD2.thread = NULL; - SDCD2.sdmmc = SDMMC2; - SDCD2.clkfreq = STM32_SDMMC2CLK; -#endif -} - -/** - * @brief Configures and activates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start(SDCDriver *sdcp) { - - /* Checking configuration, using a default if NULL has been passed.*/ - if (sdcp->config == NULL) { - sdcp->config = &sdc_default_cfg; - } - - /* If in stopped state then clocks are enabled and DMA initialized.*/ - if (sdcp->state == BLK_STOP) { -#if STM32_SDC_USE_SDMMC1 - if (&SDCD1 == sdcp) { - rccEnableSDMMC1(true); - } -#endif /* STM32_SDC_USE_SDMMC1 */ - -#if STM32_SDC_USE_SDMMC2 - if (&SDCD2 == sdcp) { - rccEnableSDMMC2(true); - } -#endif /* STM32_SDC_USE_SDMMC2 */ - } - - /* Configuration, card clock is initially stopped.*/ - sdcp->sdmmc->IDMACTRL = 0; - sdcp->sdmmc->DCTRL = 0; - sdcp->sdmmc->POWER = 0; - sdcp->sdmmc->CLKCR = 0; - sdcp->sdmmc->DTIMER = 0; - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; -} - -/** - * @brief Deactivates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop(SDCDriver *sdcp) { - - if (sdcp->state != BLK_STOP) { - - /* SDIO deactivation.*/ - sdcp->sdmmc->IDMACTRL = 0; - sdcp->sdmmc->DCTRL = 0; - sdcp->sdmmc->POWER = 0; - sdcp->sdmmc->CLKCR = 0; - sdcp->sdmmc->DTIMER = 0; - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - - /* Clock deactivation.*/ -#if STM32_SDC_USE_SDMMC1 - if (&SDCD1 == sdcp) { - rccDisableSDMMC1(); - } -#endif - -#if STM32_SDC_USE_SDMMC2 - if (&SDCD2 == sdcp) { - rccDisableSDMMC2(); - } -#endif - } -} - -/** - * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start_clk(SDCDriver *sdcp) { - - /* Initial clock setting: 400kHz, 1bit mode.*/ - sdcp->sdmmc->CLKCR = sdc_lld_clkdiv(sdcp, 400000); - sdcp->sdmmc->POWER |= SDMMC_POWER_PWRCTRL_0 | SDMMC_POWER_PWRCTRL_1; -/* TODO sdcp->sdmmc->CLKCR |= SDMMC_CLKCR_CLKEN;*/ - - /* Clock activation delay.*/ - osalThreadSleep(OSAL_MS2I(STM32_SDC_SDMMC_CLOCK_DELAY)); -} - -/** - * @brief Sets the SDIO clock to data mode (25/50 MHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] clk the clock mode - * - * @notapi - */ -void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) { - - if (SDC_CLK_50MHz == clk) { - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | -#if STM32_SDC_SDMMC_PWRSAV - sdc_lld_clkdiv(sdcp, 50000000) | SDMMC_CLKCR_PWRSAV; -#else - sdc_lld_clkdiv(sdcp, 50000000); -#endif - } - else { -#if STM32_SDC_SDMMC_PWRSAV - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | - sdc_lld_clkdiv(sdcp, 25000000) | SDMMC_CLKCR_PWRSAV; -#else - sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | - sdc_lld_clkdiv(sdcp, 25000000); -#endif - } -} - -/** - * @brief Stops the SDIO clock. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop_clk(SDCDriver *sdcp) { - - sdcp->sdmmc->CLKCR = 0; - sdcp->sdmmc->POWER = 0; -} - -/** - * @brief Switches the bus to 1, 4 or 8 bits mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] mode bus mode - * - * @notapi - */ -void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { - uint32_t clk = sdcp->sdmmc->CLKCR & ~SDMMC_CLKCR_WIDBUS; - - switch (mode) { - case SDC_MODE_1BIT: - sdcp->sdmmc->CLKCR = clk; - break; - case SDC_MODE_4BIT: - sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_0; - break; - case SDC_MODE_8BIT: - sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_1; - break; - } -} - -/** - * @brief Sends an SDIO command with no response expected. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * - * @notapi - */ -void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_CPSMEN; - while ((sdcp->sdmmc->STA & SDMMC_STA_CMDSENT) == 0) - ; - sdcp->sdmmc->ICR = SDMMC_ICR_CMDSENTC; -} - -/** - * @brief Sends an SDIO command with a short response expected. - * @note The CRC is not verified. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; - while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL)) == 0) - ; - sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL); - if ((sta & (SDMMC_STA_CTIMEOUT)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - *resp = sdcp->sdmmc->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a short response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; - while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL)) == 0) - ; - sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL); - if ((sta & (SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - *resp = sdcp->sdmmc->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a long response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (four words) - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - (void)sdcp; - - sdcp->sdmmc->ARG = arg; - sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_WAITRESP_1 | - SDMMC_CMD_CPSMEN; - while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL)) == 0) - ; - sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | - SDMMC_STA_CCRCFAIL); - if ((sta & (SDMMC_STA_ERROR_MASK)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return HAL_FAILED; - } - /* Save bytes in reverse order because MSB in response comes first.*/ - *resp++ = sdcp->sdmmc->RESP4; - *resp++ = sdcp->sdmmc->RESP3; - *resp++ = sdcp->sdmmc->RESP2; - *resp = sdcp->sdmmc->RESP1; - return HAL_SUCCESS; -} - -/** - * @brief Reads special registers using data bus. - * @details Needs only during card detection procedure. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] buf pointer to the read buffer - * @param[in] bytes number of bytes to read - * @param[in] cmd card command - * @param[in] arg argument for command - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, - uint8_t cmd, uint32_t arg) { - uint32_t resp[1]; - - if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes)) - goto error; - - if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | cmd, arg, resp) || - MMCSD_R1_ERROR(resp[0])) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, 1, resp)) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, 1, resp); - return HAL_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] blocks number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks) { - uint32_t resp[1]; - - osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); - - sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_READ_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Setting up data transfer.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | - SDMMC_MASK_DTIMEOUTIE | - SDMMC_MASK_RXOVERRIE | - SDMMC_MASK_DATAENDIE; - sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; - - /* Transfer modes.*/ - sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | - SDMMC_DCTRL_DBLOCKSIZE_3 | - SDMMC_DCTRL_DBLOCKSIZE_0; - - /* Prepares IDMA.*/ - sdcp->sdmmc->IDMABASE0 = (uint32_t)buf; - sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN; - - if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, blocks, resp); - return HAL_FAILED; -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks) { - uint32_t resp[1]; - - osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); - - sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_WRITE_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for writing.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return HAL_FAILED; - - /* Setting up data transfer.*/ - sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; - sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | - SDMMC_MASK_DTIMEOUTIE | - SDMMC_MASK_TXUNDERRIE | - SDMMC_MASK_DATAENDIE; - sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; - - /* Transfer modes.*/ - sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DBLOCKSIZE_3 | - SDMMC_DCTRL_DBLOCKSIZE_0; - - /* Prepares IDMA.*/ - sdcp->sdmmc->IDMABASE0 = (uint32_t)buf; - sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN; - - if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true) - goto error; - - if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) - goto error; - - return HAL_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, blocks, resp); - return HAL_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] blocks number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks) { - -#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < blocks; i++) { - if (sdc_lld_read_aligned(sdcp, startblk, sdcp->buf, 1)) - return HAL_FAILED; - memcpy(buf, sdcp->buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - startblk++; - } - return HAL_SUCCESS; - } -#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); -#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_read_aligned(sdcp, startblk, buf, blocks); -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] blocks number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks) { - -#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < blocks; i++) { - memcpy(sdcp->buf, buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - if (sdc_lld_write_aligned(sdcp, startblk, sdcp->buf, 1)) - return HAL_FAILED; - startblk++; - } - return HAL_SUCCESS; - } -#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); -#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_write_aligned(sdcp, startblk, buf, blocks); -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool sdc_lld_sync(SDCDriver *sdcp) { - - /* CHTODO: Implement.*/ - (void)sdcp; - return HAL_SUCCESS; -} - -/** - * @brief Shared service routine. - * - * @param[in] sdcp pointer to the @p SDCDriver object - */ -void sdc_lld_serve_interrupt(SDCDriver *sdcp) { - - /* Disables the source but the status flags are not reset because the - read/write functions needs to check them.*/ - sdcp->sdmmc->MASK = 0; - - osalSysLockFromISR(); - osalThreadResumeI(&sdcp->thread, MSG_OK); - osalSysUnlockFromISR(); -} - -#endif /* HAL_USE_SDC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SDMMCv2/hal_sdc_lld.c + * @brief STM32 SDC subsystem low level driver source. + * + * @addtogroup SDC + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SDMMC_ICR_ALL_FLAGS 0xFFFFFFFFU + +#define SDMMC_STA_ERROR_MASK \ + (SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | \ + SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | \ + SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SDCD1 driver identifier.*/ +#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__) +SDCDriver SDCD1; +#endif + +/** @brief SDCD2 driver identifier.*/ +#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__) +SDCDriver SDCD2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief SDIO default configuration. + */ +static const SDCConfig sdc_default_cfg = { + SDC_MODE_4BIT +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Calculates a clock divider for the specified frequency. + * @note The divider is calculated to not exceed the required frequency + * in case of non-integer division. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] f required frequency + */ +static uint32_t sdc_lld_clkdiv(SDCDriver *sdcp, uint32_t f) { + + if (f >= sdcp->clkfreq) { + return 0; + } + + return (sdcp->clkfreq + (f * 2) - 1) / (f * 2); +} + +/** + * @brief Prepares to handle read transaction. + * @details Designed for read special registers from card. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] buf pointer to the read buffer + * @param[in] bytes number of bytes to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp, + uint8_t *buf, uint32_t bytes) { + osalDbgCheck(bytes < 0x1000000); + + sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_READ_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Setting up data transfer.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | + SDMMC_MASK_DTIMEOUTIE | + SDMMC_MASK_RXOVERRIE | + SDMMC_MASK_DATAENDIE; + sdcp->sdmmc->DLEN = bytes; + + /* Transfer modes.*/ + sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | + SDMMC_DCTRL_DTMODE_0; /* Multibyte data transfer.*/ + + /* Prepares IDMA.*/ + sdcp->sdmmc->IDMABASE0 = (uint32_t)buf; + sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN; + + return HAL_SUCCESS; +} + +/** + * @brief Prepares card to handle read transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to read + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Send read multiple blocks command to card.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_READ_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + else { + /* Send read single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_READ_SINGLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Prepares card to handle write transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to write + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Write multiple blocks command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + else { + /* Write single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_WRITE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Wait end of data transaction and performs finalizations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + */ +static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, + uint32_t *resp) { + + /* Note the mask is checked before going to sleep because the interrupt + may have occurred before reaching the critical zone.*/ + osalSysLock(); + if (sdcp->sdmmc->MASK != 0) + osalThreadSuspendS(&sdcp->thread); + + /* Stopping operations.*/ + sdcp->sdmmc->IDMACTRL = 0; + sdcp->sdmmc->MASK = 0; + sdcp->sdmmc->DCTRL = 0; + + if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) { + osalSysUnlock(); + return HAL_FAILED; + } + + /* Clearing status.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + osalSysUnlock(); + + /* Finalize transaction.*/ + if (n > 1) + return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); + + return HAL_SUCCESS; +} + +/** + * @brief Gets SDC errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] sta value of the STA register + * + * @notapi + */ +static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { + uint32_t errors = SDC_NO_ERROR; + + if (sta & SDMMC_STA_CCRCFAIL) + errors |= SDC_CMD_CRC_ERROR; + if (sta & SDMMC_STA_DCRCFAIL) + errors |= SDC_DATA_CRC_ERROR; + if (sta & SDMMC_STA_CTIMEOUT) + errors |= SDC_COMMAND_TIMEOUT; + if (sta & SDMMC_STA_DTIMEOUT) + errors |= SDC_DATA_TIMEOUT; + if (sta & SDMMC_STA_TXUNDERR) + errors |= SDC_TX_UNDERRUN; + if (sta & SDMMC_STA_RXOVERR) + errors |= SDC_RX_OVERRUN; +/* if (sta & SDMMC_STA_STBITERR) + errors |= SDC_STARTBIT_ERROR;*/ + + sdcp->errors |= errors; +} + +/** + * @brief Performs clean transaction stopping in case of errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @notapi + */ +static void sdc_lld_error_cleanup(SDCDriver *sdcp, + uint32_t n, + uint32_t *resp) { + uint32_t sta = sdcp->sdmmc->STA; + + /* Clearing status.*/ + sta = sdcp->sdmmc->STA; + sdcp->sdmmc->ICR = sta; + sdc_lld_collect_errors(sdcp, sta); + + if (n > 1) + sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SDC driver initialization. + * + * @notapi + */ +void sdc_lld_init(void) { + +#if STM32_SDC_USE_SDMMC1 + sdcObjectInit(&SDCD1); + SDCD1.thread = NULL; + SDCD1.sdmmc = SDMMC1; + SDCD1.clkfreq = STM32_SDMMC1CLK; +#endif + +#if STM32_SDC_USE_SDMMC2 + sdcObjectInit(&SDCD2); + SDCD2.thread = NULL; + SDCD2.sdmmc = SDMMC2; + SDCD2.clkfreq = STM32_SDMMC2CLK; +#endif +} + +/** + * @brief Configures and activates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start(SDCDriver *sdcp) { + + /* Checking configuration, using a default if NULL has been passed.*/ + if (sdcp->config == NULL) { + sdcp->config = &sdc_default_cfg; + } + + /* If in stopped state then clocks are enabled and DMA initialized.*/ + if (sdcp->state == BLK_STOP) { +#if STM32_SDC_USE_SDMMC1 + if (&SDCD1 == sdcp) { + rccEnableSDMMC1(true); + } +#endif /* STM32_SDC_USE_SDMMC1 */ + +#if STM32_SDC_USE_SDMMC2 + if (&SDCD2 == sdcp) { + rccEnableSDMMC2(true); + } +#endif /* STM32_SDC_USE_SDMMC2 */ + } + + /* Configuration, card clock is initially stopped.*/ + sdcp->sdmmc->IDMACTRL = 0; + sdcp->sdmmc->DCTRL = 0; + sdcp->sdmmc->POWER = 0; + sdcp->sdmmc->CLKCR = 0; + sdcp->sdmmc->DTIMER = 0; + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; +} + +/** + * @brief Deactivates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop(SDCDriver *sdcp) { + + if (sdcp->state != BLK_STOP) { + + /* SDIO deactivation.*/ + sdcp->sdmmc->IDMACTRL = 0; + sdcp->sdmmc->DCTRL = 0; + sdcp->sdmmc->POWER = 0; + sdcp->sdmmc->CLKCR = 0; + sdcp->sdmmc->DTIMER = 0; + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + + /* Clock deactivation.*/ +#if STM32_SDC_USE_SDMMC1 + if (&SDCD1 == sdcp) { + rccDisableSDMMC1(); + } +#endif + +#if STM32_SDC_USE_SDMMC2 + if (&SDCD2 == sdcp) { + rccDisableSDMMC2(); + } +#endif + } +} + +/** + * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start_clk(SDCDriver *sdcp) { + + /* Initial clock setting: 400kHz, 1bit mode.*/ + sdcp->sdmmc->CLKCR = sdc_lld_clkdiv(sdcp, 400000); + sdcp->sdmmc->POWER |= SDMMC_POWER_PWRCTRL_0 | SDMMC_POWER_PWRCTRL_1; +/* TODO sdcp->sdmmc->CLKCR |= SDMMC_CLKCR_CLKEN;*/ + + /* Clock activation delay.*/ + osalThreadSleep(OSAL_MS2I(STM32_SDC_SDMMC_CLOCK_DELAY)); +} + +/** + * @brief Sets the SDIO clock to data mode (25/50 MHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] clk the clock mode + * + * @notapi + */ +void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) { + + if (SDC_CLK_50MHz == clk) { + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | +#if STM32_SDC_SDMMC_PWRSAV + sdc_lld_clkdiv(sdcp, 50000000) | SDMMC_CLKCR_PWRSAV; +#else + sdc_lld_clkdiv(sdcp, 50000000); +#endif + } + else { +#if STM32_SDC_SDMMC_PWRSAV + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | + sdc_lld_clkdiv(sdcp, 25000000) | SDMMC_CLKCR_PWRSAV; +#else + sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | + sdc_lld_clkdiv(sdcp, 25000000); +#endif + } +} + +/** + * @brief Stops the SDIO clock. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop_clk(SDCDriver *sdcp) { + + sdcp->sdmmc->CLKCR = 0; + sdcp->sdmmc->POWER = 0; +} + +/** + * @brief Switches the bus to 1, 4 or 8 bits mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] mode bus mode + * + * @notapi + */ +void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { + uint32_t clk = sdcp->sdmmc->CLKCR & ~SDMMC_CLKCR_WIDBUS; + + switch (mode) { + case SDC_MODE_1BIT: + sdcp->sdmmc->CLKCR = clk; + break; + case SDC_MODE_4BIT: + sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_0; + break; + case SDC_MODE_8BIT: + sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_1; + break; + } +} + +/** + * @brief Sends an SDIO command with no response expected. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * + * @notapi + */ +void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_CPSMEN; + while ((sdcp->sdmmc->STA & SDMMC_STA_CMDSENT) == 0) + ; + sdcp->sdmmc->ICR = SDMMC_ICR_CMDSENTC; +} + +/** + * @brief Sends an SDIO command with a short response expected. + * @note The CRC is not verified. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; + while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL)) == 0) + ; + sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL); + if ((sta & (SDMMC_STA_CTIMEOUT)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + *resp = sdcp->sdmmc->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a short response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; + while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL)) == 0) + ; + sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL); + if ((sta & (SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + *resp = sdcp->sdmmc->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a long response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (four words) + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + (void)sdcp; + + sdcp->sdmmc->ARG = arg; + sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_WAITRESP_1 | + SDMMC_CMD_CPSMEN; + while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL)) == 0) + ; + sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | + SDMMC_STA_CCRCFAIL); + if ((sta & (SDMMC_STA_ERROR_MASK)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return HAL_FAILED; + } + /* Save bytes in reverse order because MSB in response comes first.*/ + *resp++ = sdcp->sdmmc->RESP4; + *resp++ = sdcp->sdmmc->RESP3; + *resp++ = sdcp->sdmmc->RESP2; + *resp = sdcp->sdmmc->RESP1; + return HAL_SUCCESS; +} + +/** + * @brief Reads special registers using data bus. + * @details Needs only during card detection procedure. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] buf pointer to the read buffer + * @param[in] bytes number of bytes to read + * @param[in] cmd card command + * @param[in] arg argument for command + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, + uint8_t cmd, uint32_t arg) { + uint32_t resp[1]; + + if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes)) + goto error; + + if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | cmd, arg, resp) || + MMCSD_R1_ERROR(resp[0])) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, 1, resp)) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, 1, resp); + return HAL_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] blocks number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks) { + uint32_t resp[1]; + + osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); + + sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_READ_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Setting up data transfer.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | + SDMMC_MASK_DTIMEOUTIE | + SDMMC_MASK_RXOVERRIE | + SDMMC_MASK_DATAENDIE; + sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; + + /* Transfer modes.*/ + sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR | + SDMMC_DCTRL_DBLOCKSIZE_3 | + SDMMC_DCTRL_DBLOCKSIZE_0; + + /* Prepares IDMA.*/ + sdcp->sdmmc->IDMABASE0 = (uint32_t)buf; + sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN; + + if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, blocks, resp); + return HAL_FAILED; +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks) { + uint32_t resp[1]; + + osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE); + + sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_WRITE_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for writing.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return HAL_FAILED; + + /* Setting up data transfer.*/ + sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS; + sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE | + SDMMC_MASK_DTIMEOUTIE | + SDMMC_MASK_TXUNDERRIE | + SDMMC_MASK_DATAENDIE; + sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE; + + /* Transfer modes.*/ + sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DBLOCKSIZE_3 | + SDMMC_DCTRL_DBLOCKSIZE_0; + + /* Prepares IDMA.*/ + sdcp->sdmmc->IDMABASE0 = (uint32_t)buf; + sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN; + + if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true) + goto error; + + if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true) + goto error; + + return HAL_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, blocks, resp); + return HAL_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] blocks number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks) { + +#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < blocks; i++) { + if (sdc_lld_read_aligned(sdcp, startblk, sdcp->buf, 1)) + return HAL_FAILED; + memcpy(buf, sdcp->buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + startblk++; + } + return HAL_SUCCESS; + } +#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); +#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_read_aligned(sdcp, startblk, buf, blocks); +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] blocks number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks) { + +#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < blocks; i++) { + memcpy(sdcp->buf, buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + if (sdc_lld_write_aligned(sdcp, startblk, sdcp->buf, 1)) + return HAL_FAILED; + startblk++; + } + return HAL_SUCCESS; + } +#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer"); +#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_write_aligned(sdcp, startblk, buf, blocks); +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdc_lld_sync(SDCDriver *sdcp) { + + /* CHTODO: Implement.*/ + (void)sdcp; + return HAL_SUCCESS; +} + +/** + * @brief Shared service routine. + * + * @param[in] sdcp pointer to the @p SDCDriver object + */ +void sdc_lld_serve_interrupt(SDCDriver *sdcp) { + + /* Disables the source but the status flags are not reset because the + read/write functions needs to check them.*/ + sdcp->sdmmc->MASK = 0; + + osalSysLockFromISR(); + osalThreadResumeI(&sdcp->thread, MSG_OK); + osalSysUnlockFromISR(); +} + +#endif /* HAL_USE_SDC */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h b/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h index 334bf7a701..d67bb60624 100644 --- a/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h +++ b/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h @@ -1,301 +1,301 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SDMMCv2/hal_sdc_lld.h - * @brief STM32 SDC subsystem low level driver header. - * - * @addtogroup SDC - * @{ - */ - -#ifndef HAL_SDC_LLD_H -#define HAL_SDC_LLD_H - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SDMMC1 driver enable switch. - * @details If set to @p TRUE the support for SDMMC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SDC_USE_SDMMC1) || defined(__DOXYGEN__) -#define STM32_SDC_USE_SDMMC1 FALSE -#endif - -/** - * @brief SDMMC2 driver enable switch. - * @details If set to @p TRUE the support for SDMMC2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SDC_USE_SDMMC2) || defined(__DOXYGEN__) -#define STM32_SDC_USE_SDMMC2 FALSE -#endif - -/** - * @brief Support for unaligned transfers. - * @note Unaligned transfers are much slower. - */ -#if !defined(STM32_SDC_SDMMC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE -#endif - -/** - * @brief Write timeout in card clock cycles. - */ -#if !defined(STM32_SDC_SDMMC_WRITE_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000000 -#endif - -/** - * @brief Read timeout in card clock cycles. - */ -#if !defined(STM32_SDC_SDMMC_READ_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_READ_TIMEOUT 1000000 -#endif - -/** - * @brief Card clock activation delay in milliseconds. - */ -#if !defined(STM32_SDC_SDMMC_CLOCK_DELAY) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_CLOCK_DELAY 10 -#endif - -/** - * @brief Card clock power saving enable. - */ -#if !defined(STM32_SDC_SDMMC_PWRSAV) || defined(__DOXYGEN__) -#define STM32_SDC_SDMMC_PWRSAV TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Registry checks.*/ -#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_HANDLER)) || \ - (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_HANDLER)) -#error "STM32_SDMMCx_HANDLER not defined in registry" -#endif - -#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_NUMBER)) || \ - (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_NUMBER)) -#error "STM32_SDMMCx_NUMBER not defined in registry" -#endif - -/* Units checks.*/ -#if STM32_SDC_USE_SDMMC1 && !STM32_HAS_SDMMC1 -#error "SDMMC1 not present in the selected device" -#endif - -#if STM32_SDC_USE_SDMMC2 && !STM32_HAS_SDMMC2 -#error "SDMMC2 not present in the selected device" -#endif - -#if !STM32_SDC_USE_SDMMC1 && !STM32_SDC_USE_SDMMC2 -#error "SDC driver activated but no SDMMC peripheral assigned" -#endif - -/* Clock related tests.*/ -#if STM32_HAS_SDMMC1 && !defined(STM32_SDMMC1CLK) -#error "STM32_SDMMC1CLK not defined" -#endif - -/* Clock related tests.*/ -#if STM32_HAS_SDMMC2 && !defined(STM32_SDMMC2CLK) -#error "STM32_SDMMC2CLK not defined" -#endif - -#if !defined(STM32_HCLK) -#error "STM32_HCLK not defined" -#endif - -#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK * 10 > STM32_HCLK * 7) -#error "STM32_SDMMC1CLK must not exceed STM32_HCLK * 0.7" -#endif - -#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK * 10 > STM32_HCLK * 7) -#error "STM32_SDMMC2CLK must not exceed STM32_HCLK * 0.7" -#endif - -#if !defined(STM32_SDMMC_MAXCLK) -#define STM32_SDMMC_MAXCLK 50000000 -#endif - -#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK > STM32_SDMMC_MAXCLK) -#error "STM32_SDMMC1CLK must not exceed STM32_SDMMC_MAXCLK" -#endif - -#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK > STM32_SDMMC_MAXCLK) -#error "STM32_SDMMC2CLK must not exceed STM32_SDMMC_MAXCLK" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of card flags. - */ -typedef uint32_t sdcmode_t; - -/** - * @brief SDC Driver condition flags type. - */ -typedef uint32_t sdcflags_t; - -/** - * @brief Type of a structure representing an SDC driver. - */ -typedef struct SDCDriver SDCDriver; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Bus width. - */ - sdcbusmode_t bus_width; - /* End of the mandatory fields.*/ -} SDCConfig; - -/** - * @brief @p SDCDriver specific methods. - */ -#define _sdc_driver_methods \ - _mmcsd_block_device_methods - -/** - * @extends MMCSDBlockDeviceVMT - * - * @brief @p SDCDriver virtual methods table. - */ -struct SDCDriverVMT { - _sdc_driver_methods -}; - -/** - * @brief Structure representing an SDC driver. - */ -struct SDCDriver { - /** - * @brief Virtual Methods Table. - */ - const struct SDCDriverVMT *vmt; - _mmcsd_block_device_data - /** - * @brief Current configuration data. - */ - const SDCConfig *config; - /** - * @brief Various flags regarding the mounted card. - */ - sdcmode_t cardmode; - /** - * @brief Errors flags. - */ - sdcflags_t errors; - /** - * @brief Card RCA. - */ - uint32_t rca; - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion IRQ. - */ - thread_reference_t thread; - /** - * @brief Pointer to the SDMMC registers block. - * @note Needed for debugging aid. - */ - SDMMC_TypeDef *sdmmc; - /** - * @brief Input clock frequency. - */ - uint32_t clkfreq; - /** - * @brief Buffer for internal operations. - */ - uint8_t buf[MMCSD_BLOCK_SIZE]; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SDC_USE_SDMMC1 && !defined(__DOXYGEN__) -extern SDCDriver SDCD1; -#endif - -#if STM32_SDC_USE_SDMMC2 && !defined(__DOXYGEN__) -extern SDCDriver SDCD2; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sdc_lld_init(void); - void sdc_lld_start(SDCDriver *sdcp); - void sdc_lld_stop(SDCDriver *sdcp); - void sdc_lld_start_clk(SDCDriver *sdcp); - void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk); - void sdc_lld_stop_clk(SDCDriver *sdcp); - void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); - void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); - bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, - uint8_t cmd, uint32_t argument); - bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t blocks); - bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t blocks); - bool sdc_lld_sync(SDCDriver *sdcp); - bool sdc_lld_is_card_inserted(SDCDriver *sdcp); - bool sdc_lld_is_write_protected(SDCDriver *sdcp); - void sdc_lld_serve_interrupt(SDCDriver *sdcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SDC */ - -#endif /* HAL_SDC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SDMMCv2/hal_sdc_lld.h + * @brief STM32 SDC subsystem low level driver header. + * + * @addtogroup SDC + * @{ + */ + +#ifndef HAL_SDC_LLD_H +#define HAL_SDC_LLD_H + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SDMMC1 driver enable switch. + * @details If set to @p TRUE the support for SDMMC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SDC_USE_SDMMC1) || defined(__DOXYGEN__) +#define STM32_SDC_USE_SDMMC1 FALSE +#endif + +/** + * @brief SDMMC2 driver enable switch. + * @details If set to @p TRUE the support for SDMMC2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SDC_USE_SDMMC2) || defined(__DOXYGEN__) +#define STM32_SDC_USE_SDMMC2 FALSE +#endif + +/** + * @brief Support for unaligned transfers. + * @note Unaligned transfers are much slower. + */ +#if !defined(STM32_SDC_SDMMC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#endif + +/** + * @brief Write timeout in card clock cycles. + */ +#if !defined(STM32_SDC_SDMMC_WRITE_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000000 +#endif + +/** + * @brief Read timeout in card clock cycles. + */ +#if !defined(STM32_SDC_SDMMC_READ_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000000 +#endif + +/** + * @brief Card clock activation delay in milliseconds. + */ +#if !defined(STM32_SDC_SDMMC_CLOCK_DELAY) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#endif + +/** + * @brief Card clock power saving enable. + */ +#if !defined(STM32_SDC_SDMMC_PWRSAV) || defined(__DOXYGEN__) +#define STM32_SDC_SDMMC_PWRSAV TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks.*/ +#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_HANDLER)) || \ + (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_HANDLER)) +#error "STM32_SDMMCx_HANDLER not defined in registry" +#endif + +#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_NUMBER)) || \ + (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_NUMBER)) +#error "STM32_SDMMCx_NUMBER not defined in registry" +#endif + +/* Units checks.*/ +#if STM32_SDC_USE_SDMMC1 && !STM32_HAS_SDMMC1 +#error "SDMMC1 not present in the selected device" +#endif + +#if STM32_SDC_USE_SDMMC2 && !STM32_HAS_SDMMC2 +#error "SDMMC2 not present in the selected device" +#endif + +#if !STM32_SDC_USE_SDMMC1 && !STM32_SDC_USE_SDMMC2 +#error "SDC driver activated but no SDMMC peripheral assigned" +#endif + +/* Clock related tests.*/ +#if STM32_HAS_SDMMC1 && !defined(STM32_SDMMC1CLK) +#error "STM32_SDMMC1CLK not defined" +#endif + +/* Clock related tests.*/ +#if STM32_HAS_SDMMC2 && !defined(STM32_SDMMC2CLK) +#error "STM32_SDMMC2CLK not defined" +#endif + +#if !defined(STM32_HCLK) +#error "STM32_HCLK not defined" +#endif + +#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK * 10 > STM32_HCLK * 7) +#error "STM32_SDMMC1CLK must not exceed STM32_HCLK * 0.7" +#endif + +#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK * 10 > STM32_HCLK * 7) +#error "STM32_SDMMC2CLK must not exceed STM32_HCLK * 0.7" +#endif + +#if !defined(STM32_SDMMC_MAXCLK) +#define STM32_SDMMC_MAXCLK 50000000 +#endif + +#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK > STM32_SDMMC_MAXCLK) +#error "STM32_SDMMC1CLK must not exceed STM32_SDMMC_MAXCLK" +#endif + +#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK > STM32_SDMMC_MAXCLK) +#error "STM32_SDMMC2CLK must not exceed STM32_SDMMC_MAXCLK" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of card flags. + */ +typedef uint32_t sdcmode_t; + +/** + * @brief SDC Driver condition flags type. + */ +typedef uint32_t sdcflags_t; + +/** + * @brief Type of a structure representing an SDC driver. + */ +typedef struct SDCDriver SDCDriver; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Bus width. + */ + sdcbusmode_t bus_width; + /* End of the mandatory fields.*/ +} SDCConfig; + +/** + * @brief @p SDCDriver specific methods. + */ +#define _sdc_driver_methods \ + _mmcsd_block_device_methods + +/** + * @extends MMCSDBlockDeviceVMT + * + * @brief @p SDCDriver virtual methods table. + */ +struct SDCDriverVMT { + _sdc_driver_methods +}; + +/** + * @brief Structure representing an SDC driver. + */ +struct SDCDriver { + /** + * @brief Virtual Methods Table. + */ + const struct SDCDriverVMT *vmt; + _mmcsd_block_device_data + /** + * @brief Current configuration data. + */ + const SDCConfig *config; + /** + * @brief Various flags regarding the mounted card. + */ + sdcmode_t cardmode; + /** + * @brief Errors flags. + */ + sdcflags_t errors; + /** + * @brief Card RCA. + */ + uint32_t rca; + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion IRQ. + */ + thread_reference_t thread; + /** + * @brief Pointer to the SDMMC registers block. + * @note Needed for debugging aid. + */ + SDMMC_TypeDef *sdmmc; + /** + * @brief Input clock frequency. + */ + uint32_t clkfreq; + /** + * @brief Buffer for internal operations. + */ + uint8_t buf[MMCSD_BLOCK_SIZE]; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SDC_USE_SDMMC1 && !defined(__DOXYGEN__) +extern SDCDriver SDCD1; +#endif + +#if STM32_SDC_USE_SDMMC2 && !defined(__DOXYGEN__) +extern SDCDriver SDCD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sdc_lld_init(void); + void sdc_lld_start(SDCDriver *sdcp); + void sdc_lld_stop(SDCDriver *sdcp); + void sdc_lld_start_clk(SDCDriver *sdcp); + void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk); + void sdc_lld_stop_clk(SDCDriver *sdcp); + void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); + void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); + bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes, + uint8_t cmd, uint32_t argument); + bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t blocks); + bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t blocks); + bool sdc_lld_sync(SDCDriver *sdcp); + bool sdc_lld_is_card_inserted(SDCDriver *sdcp); + bool sdc_lld_is_write_protected(SDCDriver *sdcp); + void sdc_lld_serve_interrupt(SDCDriver *sdcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SDC */ + +#endif /* HAL_SDC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv1/driver.mk b/os/hal/ports/STM32/LLD/SPIv1/driver.mk index 1af9692f9d..619ff93196 100644 --- a/os/hal/ports/STM32/LLD/SPIv1/driver.mk +++ b/os/hal/ports/STM32/LLD/SPIv1/driver.mk @@ -1,13 +1,13 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c -endif -ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c +endif +ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1 diff --git a/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c b/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c index 235d2b8132..4025bee3ed 100644 --- a/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c @@ -1,584 +1,584 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv1/hal_i2s_lld.c - * @brief STM32 I2S subsystem low level driver source. - * - * @addtogroup I2S - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define I2S1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_RX_DMA_STREAM, \ - STM32_SPI1_RX_DMA_CHN) - -#define I2S1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_TX_DMA_STREAM, \ - STM32_SPI1_TX_DMA_CHN) - -#define I2S2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \ - STM32_SPI2_RX_DMA_CHN) - -#define I2S2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \ - STM32_SPI2_TX_DMA_CHN) - -#define I2S3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \ - STM32_SPI3_RX_DMA_CHN) - -#define I2S3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \ - STM32_SPI3_TX_DMA_CHN) - -/* - * Static I2S settings for I2S1. - */ -#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG 0 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 -#endif -#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ - SPI_I2SCFGR_I2SCFG_0) -#endif -#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ - -/* - * Static I2S settings for I2S2. - */ -#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG 0 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 -#endif -#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ - SPI_I2SCFGR_I2SCFG_0) -#endif -#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ - -/* - * Static I2S settings for I2S3. - */ -#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG 0 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 -#endif -#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ - SPI_I2SCFGR_I2SCFG_0) -#endif -#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2S1 driver identifier.*/ -#if STM32_I2S_USE_SPI1 || defined(__DOXYGEN__) -I2SDriver I2SD1; -#endif - -/** @brief I2S2 driver identifier.*/ -#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__) -I2SDriver I2SD2; -#endif - -/** @brief I2S3 driver identifier.*/ -#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__) -I2SDriver I2SD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) || \ - STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \ - STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) -/** - * @brief Shared end-of-rx service routine. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) { - - (void)i2sp; - - /* DMA errors handling.*/ -#if defined(STM32_I2S_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2S_DMA_ERROR_HOOK(i2sp); - } -#endif - - /* Callbacks handling, note it is portable code defined in the high - level driver.*/ - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _i2s_isr_full_code(i2sp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _i2s_isr_half_code(i2sp); - } -} -#endif - -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) || \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) -/** - * @brief Shared end-of-tx service routine. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) { - - (void)i2sp; - - /* DMA errors handling.*/ -#if defined(STM32_I2S_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2S_DMA_ERROR_HOOK(i2sp); - } -#endif - - /* Callbacks handling, note it is portable code defined in the high - level driver.*/ - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _i2s_isr_full_code(i2sp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _i2s_isr_half_code(i2sp); - } -} -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2S driver initialization. - * - * @notapi - */ -void i2s_lld_init(void) { - -#if STM32_I2S_USE_SPI1 - i2sObjectInit(&I2SD1); - I2SD1.spi = SPI1; - I2SD1.cfg = STM32_I2S1_CFGR_CFG; - I2SD1.dmarx = NULL; - I2SD1.dmatx = NULL; -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) - I2SD1.rxdmamode = STM32_DMA_CR_CHSEL(I2S1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD1.rxdmamode = 0; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) - I2SD1.txdmamode = STM32_DMA_CR_CHSEL(I2S1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD1.txdmamode = 0; -#endif -#endif - -#if STM32_I2S_USE_SPI2 - i2sObjectInit(&I2SD2); - I2SD2.spi = SPI2; - I2SD2.cfg = STM32_I2S2_CFGR_CFG; - I2SD2.dmarx = NULL; - I2SD2.dmatx = NULL; -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) - I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD2.rxdmamode = 0; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) - I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD2.txdmamode = 0; -#endif -#endif - -#if STM32_I2S_USE_SPI3 - i2sObjectInit(&I2SD3); - I2SD3.spi = SPI3; - I2SD3.cfg = STM32_I2S3_CFGR_CFG; - I2SD3.dmarx = NULL; - I2SD3.dmatx = NULL; -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) - I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD3.rxdmamode = 0; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) - I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD3.txdmamode = 0; -#endif -#endif -} - -/** - * @brief Configures and activates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start(I2SDriver *i2sp) { - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (i2sp->state == I2S_STOP) { - -#if STM32_I2S_USE_SPI1 - if (&I2SD1 == i2sp) { - - /* Enabling I2S unit clock.*/ - rccEnableSPI1(true); - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) - i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI1_RX_DMA_STREAM, - STM32_I2S_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_RXDMAEN; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) - i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI1_TX_DMA_STREAM, - STM32_I2S_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_TXDMAEN; -#endif - } -#endif - -#if STM32_I2S_USE_SPI2 - if (&I2SD2 == i2sp) { - - /* Enabling I2S unit clock.*/ - rccEnableSPI2(true); - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) - i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI2_RX_DMA_STREAM, - STM32_I2S_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_RXDMAEN; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) - i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI2_TX_DMA_STREAM, - STM32_I2S_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_TXDMAEN; -#endif - } -#endif - -#if STM32_I2S_USE_SPI3 - if (&I2SD3 == i2sp) { - - /* Enabling I2S unit clock.*/ - rccEnableSPI3(true); - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) - i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI3_RX_DMA_STREAM, - STM32_I2S_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_RXDMAEN; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) - i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI3_TX_DMA_STREAM, - STM32_I2S_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_TXDMAEN; -#endif - } -#endif - } - - /* I2S (re)configuration.*/ - i2sp->spi->I2SPR = i2sp->config->i2spr; - i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD; -} - -/** - * @brief Deactivates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_stop(I2SDriver *i2sp) { - - /* If in ready state then disables the SPI clock.*/ - if (i2sp->state == I2S_READY) { - - /* SPI disable.*/ - i2sp->spi->CR2 = 0; - if (NULL != i2sp->dmarx) { - dmaStreamFreeI(i2sp->dmarx); - i2sp->dmarx = NULL; - } - if (NULL != i2sp->dmatx) { - dmaStreamFreeI(i2sp->dmatx); - i2sp->dmatx = NULL; - } - -#if STM32_I2S_USE_SPI1 - if (&I2SD1 == i2sp) - rccDisableSPI1(); -#endif - -#if STM32_I2S_USE_SPI2 - if (&I2SD2 == i2sp) - rccDisableSPI2(); -#endif - -#if STM32_I2S_USE_SPI3 - if (&I2SD3 == i2sp) - rccDisableSPI3(); -#endif - } -} - -/** - * @brief Starts a I2S data exchange. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start_exchange(I2SDriver *i2sp) { - size_t size = i2sp->config->size; - - /* In 32 bit modes the DMA has to perform double operations because fetches - are always performed using 16 bit accesses. - DATLEN CHLEN SIZE - 00 (16) 0 (16) 16 - 00 (16) 1 (32) 16 - 01 (24) X 32 - 10 (32) X 32 - 11 (NA) X NA - */ - if ((i2sp->config->i2scfgr & SPI_I2SCFGR_DATLEN) != 0) - size *= 2; - - /* RX DMA setup.*/ - if (NULL != i2sp->dmarx) { - dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode); - dmaStreamSetPeripheral(i2sp->dmarx, &i2sp->spi->DR); - dmaStreamSetMemory0(i2sp->dmarx, i2sp->config->rx_buffer); - dmaStreamSetTransactionSize(i2sp->dmarx, size); - dmaStreamEnable(i2sp->dmarx); - } - - /* TX DMA setup.*/ - if (NULL != i2sp->dmatx) { - dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode); - dmaStreamSetPeripheral(i2sp->dmatx, &i2sp->spi->DR); - dmaStreamSetMemory0(i2sp->dmatx, i2sp->config->tx_buffer); - dmaStreamSetTransactionSize(i2sp->dmatx, size); - dmaStreamEnable(i2sp->dmatx); - } - - /* Starting transfer.*/ - i2sp->spi->I2SCFGR |= SPI_I2SCFGR_I2SE; -} - -/** - * @brief Stops the ongoing data exchange. - * @details The ongoing data exchange, if any, is stopped, if the driver - * was not active the function does nothing. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_stop_exchange(I2SDriver *i2sp) { - - /* Stop TX DMA, if enabled.*/ - if (NULL != i2sp->dmatx) { - dmaStreamDisable(i2sp->dmatx); - - /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory - to wait for TXE = 1 and BSY = 0.*/ - while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE) - ; - - /* Stop SPI/I2S peripheral.*/ - i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE; - } - - /* Stop RX DMA, if enabled then draining the RX DR.*/ - if (NULL != i2sp->dmarx) { - dmaStreamDisable(i2sp->dmarx); - - /* Waiting for some data to be present in RX DR.*/ - while ((i2sp->spi->SR & SPI_SR_RXNE) != SPI_SR_RXNE) - ; - - /* Stop SPI/I2S peripheral.*/ - i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE; - - /* Purging data in DR.*/ - while ((i2sp->spi->SR & SPI_SR_RXNE) != 0) - (void) i2sp->spi->DR; - } -} - -#endif /* HAL_USE_I2S */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv1/hal_i2s_lld.c + * @brief STM32 I2S subsystem low level driver source. + * + * @addtogroup I2S + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define I2S1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_RX_DMA_STREAM, \ + STM32_SPI1_RX_DMA_CHN) + +#define I2S1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_TX_DMA_STREAM, \ + STM32_SPI1_TX_DMA_CHN) + +#define I2S2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \ + STM32_SPI2_RX_DMA_CHN) + +#define I2S2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \ + STM32_SPI2_TX_DMA_CHN) + +#define I2S3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \ + STM32_SPI3_RX_DMA_CHN) + +#define I2S3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \ + STM32_SPI3_TX_DMA_CHN) + +/* + * Static I2S settings for I2S1. + */ +#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG 0 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 +#endif +#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ + SPI_I2SCFGR_I2SCFG_0) +#endif +#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ + +/* + * Static I2S settings for I2S2. + */ +#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG 0 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 +#endif +#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ + SPI_I2SCFGR_I2SCFG_0) +#endif +#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ + +/* + * Static I2S settings for I2S3. + */ +#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG 0 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 +#endif +#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ + SPI_I2SCFGR_I2SCFG_0) +#endif +#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2S1 driver identifier.*/ +#if STM32_I2S_USE_SPI1 || defined(__DOXYGEN__) +I2SDriver I2SD1; +#endif + +/** @brief I2S2 driver identifier.*/ +#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__) +I2SDriver I2SD2; +#endif + +/** @brief I2S3 driver identifier.*/ +#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__) +I2SDriver I2SD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) || \ + STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \ + STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) +/** + * @brief Shared end-of-rx service routine. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) { + + (void)i2sp; + + /* DMA errors handling.*/ +#if defined(STM32_I2S_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2S_DMA_ERROR_HOOK(i2sp); + } +#endif + + /* Callbacks handling, note it is portable code defined in the high + level driver.*/ + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _i2s_isr_full_code(i2sp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _i2s_isr_half_code(i2sp); + } +} +#endif + +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) || \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) +/** + * @brief Shared end-of-tx service routine. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) { + + (void)i2sp; + + /* DMA errors handling.*/ +#if defined(STM32_I2S_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2S_DMA_ERROR_HOOK(i2sp); + } +#endif + + /* Callbacks handling, note it is portable code defined in the high + level driver.*/ + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _i2s_isr_full_code(i2sp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _i2s_isr_half_code(i2sp); + } +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2S driver initialization. + * + * @notapi + */ +void i2s_lld_init(void) { + +#if STM32_I2S_USE_SPI1 + i2sObjectInit(&I2SD1); + I2SD1.spi = SPI1; + I2SD1.cfg = STM32_I2S1_CFGR_CFG; + I2SD1.dmarx = NULL; + I2SD1.dmatx = NULL; +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) + I2SD1.rxdmamode = STM32_DMA_CR_CHSEL(I2S1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD1.rxdmamode = 0; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) + I2SD1.txdmamode = STM32_DMA_CR_CHSEL(I2S1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD1.txdmamode = 0; +#endif +#endif + +#if STM32_I2S_USE_SPI2 + i2sObjectInit(&I2SD2); + I2SD2.spi = SPI2; + I2SD2.cfg = STM32_I2S2_CFGR_CFG; + I2SD2.dmarx = NULL; + I2SD2.dmatx = NULL; +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) + I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD2.rxdmamode = 0; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) + I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD2.txdmamode = 0; +#endif +#endif + +#if STM32_I2S_USE_SPI3 + i2sObjectInit(&I2SD3); + I2SD3.spi = SPI3; + I2SD3.cfg = STM32_I2S3_CFGR_CFG; + I2SD3.dmarx = NULL; + I2SD3.dmatx = NULL; +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) + I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD3.rxdmamode = 0; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) + I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD3.txdmamode = 0; +#endif +#endif +} + +/** + * @brief Configures and activates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start(I2SDriver *i2sp) { + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (i2sp->state == I2S_STOP) { + +#if STM32_I2S_USE_SPI1 + if (&I2SD1 == i2sp) { + + /* Enabling I2S unit clock.*/ + rccEnableSPI1(true); + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) + i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI1_RX_DMA_STREAM, + STM32_I2S_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_RXDMAEN; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) + i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI1_TX_DMA_STREAM, + STM32_I2S_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_TXDMAEN; +#endif + } +#endif + +#if STM32_I2S_USE_SPI2 + if (&I2SD2 == i2sp) { + + /* Enabling I2S unit clock.*/ + rccEnableSPI2(true); + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) + i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI2_RX_DMA_STREAM, + STM32_I2S_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_RXDMAEN; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) + i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI2_TX_DMA_STREAM, + STM32_I2S_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_TXDMAEN; +#endif + } +#endif + +#if STM32_I2S_USE_SPI3 + if (&I2SD3 == i2sp) { + + /* Enabling I2S unit clock.*/ + rccEnableSPI3(true); + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) + i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI3_RX_DMA_STREAM, + STM32_I2S_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_RXDMAEN; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) + i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI3_TX_DMA_STREAM, + STM32_I2S_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_TXDMAEN; +#endif + } +#endif + } + + /* I2S (re)configuration.*/ + i2sp->spi->I2SPR = i2sp->config->i2spr; + i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD; +} + +/** + * @brief Deactivates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_stop(I2SDriver *i2sp) { + + /* If in ready state then disables the SPI clock.*/ + if (i2sp->state == I2S_READY) { + + /* SPI disable.*/ + i2sp->spi->CR2 = 0; + if (NULL != i2sp->dmarx) { + dmaStreamFreeI(i2sp->dmarx); + i2sp->dmarx = NULL; + } + if (NULL != i2sp->dmatx) { + dmaStreamFreeI(i2sp->dmatx); + i2sp->dmatx = NULL; + } + +#if STM32_I2S_USE_SPI1 + if (&I2SD1 == i2sp) + rccDisableSPI1(); +#endif + +#if STM32_I2S_USE_SPI2 + if (&I2SD2 == i2sp) + rccDisableSPI2(); +#endif + +#if STM32_I2S_USE_SPI3 + if (&I2SD3 == i2sp) + rccDisableSPI3(); +#endif + } +} + +/** + * @brief Starts a I2S data exchange. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start_exchange(I2SDriver *i2sp) { + size_t size = i2sp->config->size; + + /* In 32 bit modes the DMA has to perform double operations because fetches + are always performed using 16 bit accesses. + DATLEN CHLEN SIZE + 00 (16) 0 (16) 16 + 00 (16) 1 (32) 16 + 01 (24) X 32 + 10 (32) X 32 + 11 (NA) X NA + */ + if ((i2sp->config->i2scfgr & SPI_I2SCFGR_DATLEN) != 0) + size *= 2; + + /* RX DMA setup.*/ + if (NULL != i2sp->dmarx) { + dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode); + dmaStreamSetPeripheral(i2sp->dmarx, &i2sp->spi->DR); + dmaStreamSetMemory0(i2sp->dmarx, i2sp->config->rx_buffer); + dmaStreamSetTransactionSize(i2sp->dmarx, size); + dmaStreamEnable(i2sp->dmarx); + } + + /* TX DMA setup.*/ + if (NULL != i2sp->dmatx) { + dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode); + dmaStreamSetPeripheral(i2sp->dmatx, &i2sp->spi->DR); + dmaStreamSetMemory0(i2sp->dmatx, i2sp->config->tx_buffer); + dmaStreamSetTransactionSize(i2sp->dmatx, size); + dmaStreamEnable(i2sp->dmatx); + } + + /* Starting transfer.*/ + i2sp->spi->I2SCFGR |= SPI_I2SCFGR_I2SE; +} + +/** + * @brief Stops the ongoing data exchange. + * @details The ongoing data exchange, if any, is stopped, if the driver + * was not active the function does nothing. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_stop_exchange(I2SDriver *i2sp) { + + /* Stop TX DMA, if enabled.*/ + if (NULL != i2sp->dmatx) { + dmaStreamDisable(i2sp->dmatx); + + /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory + to wait for TXE = 1 and BSY = 0.*/ + while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE) + ; + + /* Stop SPI/I2S peripheral.*/ + i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE; + } + + /* Stop RX DMA, if enabled then draining the RX DR.*/ + if (NULL != i2sp->dmarx) { + dmaStreamDisable(i2sp->dmarx); + + /* Waiting for some data to be present in RX DR.*/ + while ((i2sp->spi->SR & SPI_SR_RXNE) != SPI_SR_RXNE) + ; + + /* Stop SPI/I2S peripheral.*/ + i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE; + + /* Purging data in DR.*/ + while ((i2sp->spi->SR & SPI_SR_RXNE) != 0) + (void) i2sp->spi->DR; + } +} + +#endif /* HAL_USE_I2S */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h b/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h index 37b3f2ac51..70735a772d 100644 --- a/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h +++ b/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h @@ -1,371 +1,371 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv1/hal_i2s_lld.h - * @brief STM32 I2S subsystem low level driver header. - * - * @addtogroup I2S - * @{ - */ - -#ifndef HAL_I2S_LLD_H -#define HAL_I2S_LLD_H - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Static I2S modes - * @{ - */ -#define STM32_I2S_MODE_SLAVE 0 -#define STM32_I2S_MODE_MASTER 1 -#define STM32_I2S_MODE_RX 2 -#define STM32_I2S_MODE_TX 4 -#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \ - STM32_I2S_MODE_TX) -/** @} */ - -/** - * @name Mode checks - * @{ - */ -#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER) -#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX) -#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2S1 driver enable switch. - * @details If set to @p TRUE the support for I2S1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_I2S_USE_SPI1 FALSE -#endif - -/** - * @brief I2S2 driver enable switch. - * @details If set to @p TRUE the support for I2S2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_I2S_USE_SPI2 FALSE -#endif - -/** - * @brief I2S3 driver enable switch. - * @details If set to @p TRUE the support for I2S3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_I2S_USE_SPI3 FALSE -#endif - -/** - * @brief I2S1 mode. - */ -#if !defined(STM32_I2S_SPI1_MODE) || defined(__DOXYGEN__) -#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ - STM32_I2S_MODE_RX) -#endif - -/** - * @brief I2S2 mode. - */ -#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__) -#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \ - STM32_I2S_MODE_RX) -#endif - -/** - * @brief I2S3 mode. - */ -#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) -#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \ - STM32_I2S_MODE_RX) -#endif - -/** - * @brief I2S1 interrupt priority level setting. - */ -#if !defined(STM32_I2S_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S2 interrupt priority level setting. - */ -#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S3 interrupt priority level setting. - */ -#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S3 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S DMA error hook. - */ -#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_I2S_USE_SPI1 && !STM32_SPI1_SUPPORTS_I2S -#error "SPI1 does not support I2S mode" -#endif - -#if STM32_I2S_USE_SPI2 && !STM32_SPI2_SUPPORTS_I2S -#error "SPI2 does not support I2S mode" -#endif - -#if STM32_I2S_USE_SPI3 && !STM32_SPI3_SUPPORTS_I2S -#error "SPI3 does not support I2S mode" -#endif - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) && \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) -#error "I2S1 RX and TX mode not supported in this driver implementation" -#endif - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) && \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) -#error "I2S2 RX and TX mode not supported in this driver implementation" -#endif - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) && \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) -#error "I2S3 RX and TX mode not supported in this driver implementation" -#endif - -#if STM32_I2S_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if !STM32_I2S_USE_SPI1 && !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3 -#error "I2S driver activated but no SPI peripheral assigned" -#endif - -#if STM32_I2S_USE_SPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_I2S_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2S_USE_SPI1 && (!defined(STM32_I2S_SPI1_RX_DMA_STREAM) || \ - !defined(STM32_I2S_SPI1_TX_DMA_STREAM)) -#error "SPI1 DMA streams not defined" -#endif - -#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \ - !defined(STM32_I2S_SPI2_TX_DMA_STREAM)) -#error "SPI2 DMA streams not defined" -#endif - -#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \ - !defined(STM32_I2S_SPI3_TX_DMA_STREAM)) -#error "SPI3 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2S_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 RX" -#endif - -#if STM32_I2S_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 TX" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 RX" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 TX" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 RX" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the I2S driver structure. - */ -#define i2s_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /* Calculated part of the I2SCFGR register.*/ \ - uint16_t cfg; \ - /* Receive DMA stream or @p NULL.*/ \ - const stm32_dma_stream_t *dmarx; \ - /* Transmit DMA stream or @p NULL.*/ \ - const stm32_dma_stream_t *dmatx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode - -/** - * @brief Low level fields of the I2S configuration structure. - */ -#define i2s_lld_config_fields \ - /* Configuration of the I2SCFGR register. \ - NOTE: See the STM32 reference manual, this register is used for \ - the I2S configuration, the following bits must not be \ - specified because handled directly by the driver: \ - - I2SMOD \ - - I2SE \ - - I2SCFG \ - */ \ - int16_t i2scfgr; \ - /* Configuration of the I2SPR register. \ - NOTE: See the STM32 reference manual, this register is used for \ - the I2S clock setup.*/ \ - int16_t i2spr - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_I2S_USE_SPI1 && !defined(__DOXYGEN__) -extern I2SDriver I2SD1; -#endif - -#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__) -extern I2SDriver I2SD2; -#endif - -#if STM32_I2S_USE_SPI3 && !defined(__DOXYGEN__) -extern I2SDriver I2SD3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void i2s_lld_init(void); - void i2s_lld_start(I2SDriver *i2sp); - void i2s_lld_stop(I2SDriver *i2sp); - void i2s_lld_start_exchange(I2SDriver *i2sp); - void i2s_lld_stop_exchange(I2SDriver *i2sp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2S */ - -#endif /* HAL_I2S_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv1/hal_i2s_lld.h + * @brief STM32 I2S subsystem low level driver header. + * + * @addtogroup I2S + * @{ + */ + +#ifndef HAL_I2S_LLD_H +#define HAL_I2S_LLD_H + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Static I2S modes + * @{ + */ +#define STM32_I2S_MODE_SLAVE 0 +#define STM32_I2S_MODE_MASTER 1 +#define STM32_I2S_MODE_RX 2 +#define STM32_I2S_MODE_TX 4 +#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \ + STM32_I2S_MODE_TX) +/** @} */ + +/** + * @name Mode checks + * @{ + */ +#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER) +#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX) +#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2S1 driver enable switch. + * @details If set to @p TRUE the support for I2S1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_I2S_USE_SPI1 FALSE +#endif + +/** + * @brief I2S2 driver enable switch. + * @details If set to @p TRUE the support for I2S2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_I2S_USE_SPI2 FALSE +#endif + +/** + * @brief I2S3 driver enable switch. + * @details If set to @p TRUE the support for I2S3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_I2S_USE_SPI3 FALSE +#endif + +/** + * @brief I2S1 mode. + */ +#if !defined(STM32_I2S_SPI1_MODE) || defined(__DOXYGEN__) +#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#endif + +/** + * @brief I2S2 mode. + */ +#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__) +#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#endif + +/** + * @brief I2S3 mode. + */ +#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) +#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#endif + +/** + * @brief I2S1 interrupt priority level setting. + */ +#if !defined(STM32_I2S_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S2 interrupt priority level setting. + */ +#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S3 interrupt priority level setting. + */ +#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S3 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S DMA error hook. + */ +#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_I2S_USE_SPI1 && !STM32_SPI1_SUPPORTS_I2S +#error "SPI1 does not support I2S mode" +#endif + +#if STM32_I2S_USE_SPI2 && !STM32_SPI2_SUPPORTS_I2S +#error "SPI2 does not support I2S mode" +#endif + +#if STM32_I2S_USE_SPI3 && !STM32_SPI3_SUPPORTS_I2S +#error "SPI3 does not support I2S mode" +#endif + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) && \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) +#error "I2S1 RX and TX mode not supported in this driver implementation" +#endif + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) && \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) +#error "I2S2 RX and TX mode not supported in this driver implementation" +#endif + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) && \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) +#error "I2S3 RX and TX mode not supported in this driver implementation" +#endif + +#if STM32_I2S_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if !STM32_I2S_USE_SPI1 && !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3 +#error "I2S driver activated but no SPI peripheral assigned" +#endif + +#if STM32_I2S_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_I2S_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2S_USE_SPI1 && (!defined(STM32_I2S_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_I2S_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_I2S_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_I2S_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2S_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_I2S_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the I2S driver structure. + */ +#define i2s_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /* Calculated part of the I2SCFGR register.*/ \ + uint16_t cfg; \ + /* Receive DMA stream or @p NULL.*/ \ + const stm32_dma_stream_t *dmarx; \ + /* Transmit DMA stream or @p NULL.*/ \ + const stm32_dma_stream_t *dmatx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode + +/** + * @brief Low level fields of the I2S configuration structure. + */ +#define i2s_lld_config_fields \ + /* Configuration of the I2SCFGR register. \ + NOTE: See the STM32 reference manual, this register is used for \ + the I2S configuration, the following bits must not be \ + specified because handled directly by the driver: \ + - I2SMOD \ + - I2SE \ + - I2SCFG \ + */ \ + int16_t i2scfgr; \ + /* Configuration of the I2SPR register. \ + NOTE: See the STM32 reference manual, this register is used for \ + the I2S clock setup.*/ \ + int16_t i2spr + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_I2S_USE_SPI1 && !defined(__DOXYGEN__) +extern I2SDriver I2SD1; +#endif + +#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__) +extern I2SDriver I2SD2; +#endif + +#if STM32_I2S_USE_SPI3 && !defined(__DOXYGEN__) +extern I2SDriver I2SD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void i2s_lld_init(void); + void i2s_lld_start(I2SDriver *i2sp); + void i2s_lld_stop(I2SDriver *i2sp); + void i2s_lld_start_exchange(I2SDriver *i2sp); + void i2s_lld_stop_exchange(I2SDriver *i2sp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2S */ + +#endif /* HAL_I2S_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c index 459e6b98b5..0f5d6904ee 100644 --- a/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c @@ -1,679 +1,679 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv1/hal_spi_lld.c - * @brief STM32 SPI subsystem low level driver source. - * - * @addtogroup SPI - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SPI1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ - STM32_SPI1_RX_DMA_CHN) - -#define SPI1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ - STM32_SPI1_TX_DMA_CHN) - -#define SPI2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ - STM32_SPI2_RX_DMA_CHN) - -#define SPI2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ - STM32_SPI2_TX_DMA_CHN) - -#define SPI3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ - STM32_SPI3_RX_DMA_CHN) - -#define SPI3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ - STM32_SPI3_TX_DMA_CHN) - -#define SPI4_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_RX_DMA_STREAM, \ - STM32_SPI4_RX_DMA_CHN) - -#define SPI4_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_TX_DMA_STREAM, \ - STM32_SPI4_TX_DMA_CHN) - -#define SPI5_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_RX_DMA_STREAM, \ - STM32_SPI5_RX_DMA_CHN) - -#define SPI5_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_TX_DMA_STREAM, \ - STM32_SPI5_TX_DMA_CHN) - -#define SPI6_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_RX_DMA_STREAM, \ - STM32_SPI6_RX_DMA_CHN) - -#define SPI6_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_TX_DMA_STREAM, \ - STM32_SPI6_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SPI1 driver identifier.*/ -#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) -SPIDriver SPID1; -#endif - -/** @brief SPI2 driver identifier.*/ -#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) -SPIDriver SPID2; -#endif - -/** @brief SPI3 driver identifier.*/ -#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) -SPIDriver SPID3; -#endif - -/** @brief SPI4 driver identifier.*/ -#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) -SPIDriver SPID4; -#endif - -/** @brief SPI5 driver identifier.*/ -#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) -SPIDriver SPID5; -#endif - -/** @brief SPI6 driver identifier.*/ -#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) -SPIDriver SPID6; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint16_t dummytx = 0xFFFFU; -static uint16_t dummyrx; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared end-of-rx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)flags; -#endif - - if (spip->config->circular) { - if ((flags & STM32_DMA_ISR_HTIF) != 0U) { - /* Half buffer interrupt.*/ - _spi_isr_half_code(spip); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0U) { - /* End buffer interrupt.*/ - _spi_isr_full_code(spip); - } - } - else { - /* Stopping DMAs.*/ - dmaStreamDisable(spip->dmatx); - dmaStreamDisable(spip->dmarx); - - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); - } -} - -/** - * @brief Shared end-of-tx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - (void)spip; - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)spip; - (void)flags; -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SPI driver initialization. - * - * @notapi - */ -void spi_lld_init(void) { - -#if STM32_SPI_USE_SPI1 - spiObjectInit(&SPID1); - SPID1.spi = SPI1; - SPID1.dmarx = NULL; - SPID1.dmatx = NULL; - SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI2 - spiObjectInit(&SPID2); - SPID2.spi = SPI2; - SPID2.dmarx = NULL; - SPID2.dmatx = NULL; - SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI3 - spiObjectInit(&SPID3); - SPID3.spi = SPI3; - SPID3.dmarx = NULL; - SPID3.dmatx = NULL; - SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI4 - spiObjectInit(&SPID4); - SPID4.spi = SPI4; - SPID4.dmarx = NULL; - SPID4.dmatx = NULL; - SPID4.rxdmamode = STM32_DMA_CR_CHSEL(SPI4_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID4.txdmamode = STM32_DMA_CR_CHSEL(SPI4_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI5 - spiObjectInit(&SPID5); - SPID5.spi = SPI5; - SPID5.dmarx = NULL; - SPID5.dmatx = NULL; - SPID5.rxdmamode = STM32_DMA_CR_CHSEL(SPI5_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID5.txdmamode = STM32_DMA_CR_CHSEL(SPI5_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI6 - spiObjectInit(&SPID6); - SPID6.spi = SPI6; - SPID6.dmarx = NULL; - SPID6.dmatx = NULL; - SPID6.rxdmamode = STM32_DMA_CR_CHSEL(SPI6_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID6.txdmamode = STM32_DMA_CR_CHSEL(SPI6_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_start(SPIDriver *spip) { - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (spip->state == SPI_STOP) { -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI1(true); - } -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI2(true); - } -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI3(true); - } -#endif -#if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI4(true); - } -#endif -#if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI5(true); - } -#endif -#if STM32_SPI_USE_SPI6 - if (&SPID6 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI6(true); - } -#endif - - /* DMA setup.*/ - dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); - dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); - } - - /* Configuration-specific DMA setup.*/ - if ((spip->config->cr1 & SPI_CR1_DFF) == 0) { - /* Frame width is 8 bits or smaller.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - } - else { - /* Frame width is larger than 8 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - - if (spip->config->circular) { - spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - } - else { - spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - } - - /* SPI setup and enable.*/ - spip->spi->CR1 &= ~SPI_CR1_SPE; - spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM | - SPI_CR1_SSI; - spip->spi->CR2 = spip->config->cr2 | SPI_CR2_SSOE | SPI_CR2_RXDMAEN | - SPI_CR2_TXDMAEN; - spip->spi->CR1 |= SPI_CR1_SPE; -} - -/** - * @brief Deactivates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_stop(SPIDriver *spip) { - - /* If in ready state then disables the SPI clock.*/ - if (spip->state == SPI_READY) { - - /* SPI disable.*/ - spip->spi->CR1 &= ~SPI_CR1_SPE; - spip->spi->CR1 = 0; - spip->spi->CR2 = 0; - dmaStreamFreeI(spip->dmarx); - dmaStreamFreeI(spip->dmatx); - spip->dmarx = NULL; - spip->dmatx = NULL; - -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) - rccDisableSPI1(); -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) - rccDisableSPI2(); -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) - rccDisableSPI3(); -#endif -#if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) - rccDisableSPI4(); -#endif -#if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) - rccDisableSPI5(); -#endif -#if STM32_SPI_USE_SPI6 - if (&SPID6 == spip) - rccDisableSPI6(); -#endif - } -} - -#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_select(SPIDriver *spip) { - - /* No implementation on STM32.*/ -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_unselect(SPIDriver *spip) { - - /* No implementation on STM32.*/ -} -#endif - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @notapi - */ -void spi_lld_ignore(SPIDriver *spip, size_t n) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) -/** - * @brief Aborts the ongoing SPI operation, if any. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_abort(SPIDriver *spip) { - - /* Stopping DMAs.*/ - dmaStreamDisable(spip->dmatx); - dmaStreamDisable(spip->dmarx); -} -#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ - -/** - * @brief Exchanges one frame using a polled wait. - * @details This synchronous function exchanges one frame using a polled - * synchronization method. This function is useful when exchanging - * small amount of data on high speed channels, usually in this - * situation is much more efficient just wait for completion using - * polling than suspending the thread waiting for an interrupt. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] frame the data frame to send over the SPI bus - * @return The received data frame from the SPI bus. - */ -uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { - - spip->spi->DR = frame; - while ((spip->spi->SR & SPI_SR_RXNE) == 0) - ; - return spip->spi->DR; -} - -#endif /* HAL_USE_SPI */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv1/hal_spi_lld.c + * @brief STM32 SPI subsystem low level driver source. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SPI1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ + STM32_SPI1_RX_DMA_CHN) + +#define SPI1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ + STM32_SPI1_TX_DMA_CHN) + +#define SPI2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ + STM32_SPI2_RX_DMA_CHN) + +#define SPI2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ + STM32_SPI2_TX_DMA_CHN) + +#define SPI3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ + STM32_SPI3_RX_DMA_CHN) + +#define SPI3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ + STM32_SPI3_TX_DMA_CHN) + +#define SPI4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_RX_DMA_STREAM, \ + STM32_SPI4_RX_DMA_CHN) + +#define SPI4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_TX_DMA_STREAM, \ + STM32_SPI4_TX_DMA_CHN) + +#define SPI5_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_RX_DMA_STREAM, \ + STM32_SPI5_RX_DMA_CHN) + +#define SPI5_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_TX_DMA_STREAM, \ + STM32_SPI5_TX_DMA_CHN) + +#define SPI6_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_RX_DMA_STREAM, \ + STM32_SPI6_RX_DMA_CHN) + +#define SPI6_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_TX_DMA_STREAM, \ + STM32_SPI6_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SPI1 driver identifier.*/ +#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/** @brief SPI2 driver identifier.*/ +#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/** @brief SPI3 driver identifier.*/ +#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) +SPIDriver SPID3; +#endif + +/** @brief SPI4 driver identifier.*/ +#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) +SPIDriver SPID4; +#endif + +/** @brief SPI5 driver identifier.*/ +#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) +SPIDriver SPID5; +#endif + +/** @brief SPI6 driver identifier.*/ +#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) +SPIDriver SPID6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint16_t dummytx = 0xFFFFU; +static uint16_t dummyrx; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif + + if (spip->config->circular) { + if ((flags & STM32_DMA_ISR_HTIF) != 0U) { + /* Half buffer interrupt.*/ + _spi_isr_half_code(spip); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0U) { + /* End buffer interrupt.*/ + _spi_isr_full_code(spip); + } + } + else { + /* Stopping DMAs.*/ + dmaStreamDisable(spip->dmatx); + dmaStreamDisable(spip->dmarx); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); + } +} + +/** + * @brief Shared end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { + +#if STM32_SPI_USE_SPI1 + spiObjectInit(&SPID1); + SPID1.spi = SPI1; + SPID1.dmarx = NULL; + SPID1.dmatx = NULL; + SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI2 + spiObjectInit(&SPID2); + SPID2.spi = SPI2; + SPID2.dmarx = NULL; + SPID2.dmatx = NULL; + SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI3 + spiObjectInit(&SPID3); + SPID3.spi = SPI3; + SPID3.dmarx = NULL; + SPID3.dmatx = NULL; + SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI4 + spiObjectInit(&SPID4); + SPID4.spi = SPI4; + SPID4.dmarx = NULL; + SPID4.dmatx = NULL; + SPID4.rxdmamode = STM32_DMA_CR_CHSEL(SPI4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID4.txdmamode = STM32_DMA_CR_CHSEL(SPI4_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI5 + spiObjectInit(&SPID5); + SPID5.spi = SPI5; + SPID5.dmarx = NULL; + SPID5.dmatx = NULL; + SPID5.rxdmamode = STM32_DMA_CR_CHSEL(SPI5_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID5.txdmamode = STM32_DMA_CR_CHSEL(SPI5_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI6 + spiObjectInit(&SPID6); + SPID6.spi = SPI6; + SPID6.dmarx = NULL; + SPID6.dmatx = NULL; + SPID6.rxdmamode = STM32_DMA_CR_CHSEL(SPI6_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID6.txdmamode = STM32_DMA_CR_CHSEL(SPI6_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_start(SPIDriver *spip) { + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (spip->state == SPI_STOP) { +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI1(true); + } +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI2(true); + } +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI3(true); + } +#endif +#if STM32_SPI_USE_SPI4 + if (&SPID4 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI4(true); + } +#endif +#if STM32_SPI_USE_SPI5 + if (&SPID5 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI5(true); + } +#endif +#if STM32_SPI_USE_SPI6 + if (&SPID6 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI6(true); + } +#endif + + /* DMA setup.*/ + dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); + dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); + } + + /* Configuration-specific DMA setup.*/ + if ((spip->config->cr1 & SPI_CR1_DFF) == 0) { + /* Frame width is 8 bits or smaller.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + } + else { + /* Frame width is larger than 8 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + + if (spip->config->circular) { + spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + else { + spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + + /* SPI setup and enable.*/ + spip->spi->CR1 &= ~SPI_CR1_SPE; + spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM | + SPI_CR1_SSI; + spip->spi->CR2 = spip->config->cr2 | SPI_CR2_SSOE | SPI_CR2_RXDMAEN | + SPI_CR2_TXDMAEN; + spip->spi->CR1 |= SPI_CR1_SPE; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->state == SPI_READY) { + + /* SPI disable.*/ + spip->spi->CR1 &= ~SPI_CR1_SPE; + spip->spi->CR1 = 0; + spip->spi->CR2 = 0; + dmaStreamFreeI(spip->dmarx); + dmaStreamFreeI(spip->dmatx); + spip->dmarx = NULL; + spip->dmatx = NULL; + +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) + rccDisableSPI1(); +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) + rccDisableSPI2(); +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) + rccDisableSPI3(); +#endif +#if STM32_SPI_USE_SPI4 + if (&SPID4 == spip) + rccDisableSPI4(); +#endif +#if STM32_SPI_USE_SPI5 + if (&SPID5 == spip) + rccDisableSPI5(); +#endif +#if STM32_SPI_USE_SPI6 + if (&SPID6 == spip) + rccDisableSPI6(); +#endif + } +} + +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + /* No implementation on STM32.*/ +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + /* No implementation on STM32.*/ +} +#endif + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @notapi + */ +void spi_lld_ignore(SPIDriver *spip, size_t n) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) +/** + * @brief Aborts the ongoing SPI operation, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_abort(SPIDriver *spip) { + + /* Stopping DMAs.*/ + dmaStreamDisable(spip->dmatx); + dmaStreamDisable(spip->dmarx); +} +#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { + + spip->spi->DR = frame; + while ((spip->spi->SR & SPI_SR_RXNE) == 0) + ; + return spip->spi->DR; +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h b/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h index 09a6eec01d..f6841feb0b 100644 --- a/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h +++ b/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h @@ -1,495 +1,495 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv1/hal_spi_lld.h - * @brief STM32 SPI subsystem low level driver header. - * - * @addtogroup SPI - * @{ - */ - -#ifndef HAL_SPI_LLD_H -#define HAL_SPI_LLD_H - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Circular mode support flag. - */ -#define SPI_SUPPORTS_CIRCULAR TRUE - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SPI1 driver enable switch. - * @details If set to @p TRUE the support for SPI1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI1 FALSE -#endif - -/** - * @brief SPI2 driver enable switch. - * @details If set to @p TRUE the support for SPI2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI2 FALSE -#endif - -/** - * @brief SPI3 driver enable switch. - * @details If set to @p TRUE the support for SPI3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI3 FALSE -#endif - -/** - * @brief SPI4 driver enable switch. - * @details If set to @p TRUE the support for SPI4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI4 FALSE -#endif - -/** - * @brief SPI5 driver enable switch. - * @details If set to @p TRUE the support for SPI5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI5 FALSE -#endif - -/** - * @brief SPI6 driver enable switch. - * @details If set to @p TRUE the support for SPI6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI6 FALSE -#endif - -/** - * @brief SPI1 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI2 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI3 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI4 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI4_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI5 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI5_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI6 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI6_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI4_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI5 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI5_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI6 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI6_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI DMA error hook. - */ -#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 -#error "SPI4 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 -#error "SPI5 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 -#error "SPI6 not present in the selected device" -#endif - -#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ - !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 -#error "SPI driver activated but no SPI peripheral assigned" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI4" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI5" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI6" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI4" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI5" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI6" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) -#error "SPI1 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) -#error "SPI2 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) -#error "SPI3 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) -#error "SPI4 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) -#error "SPI5 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI6_TX_DMA_STREAM)) -#error "SPI6 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 RX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 TX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 RX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 TX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 RX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 TX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI4 RX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI4 TX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI5 RX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI5 TX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI6 RX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI6 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD -#error "SPI_SELECT_MODE_LLD not supported by this driver" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the SPI driver structure. - */ -#define spi_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /* Receive DMA stream.*/ \ - const stm32_dma_stream_t *dmarx; \ - /* Transmit DMA stream.*/ \ - const stm32_dma_stream_t *dmatx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode - -/** - * @brief Low level fields of the SPI configuration structure. - */ -#define spi_lld_config_fields \ - /* SPI CR1 register initialization data.*/ \ - uint16_t cr1; \ - /* SPI CR2 register initialization data.*/ \ - uint16_t cr2 - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) -extern SPIDriver SPID1; -#endif - -#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) -extern SPIDriver SPID2; -#endif - -#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) -extern SPIDriver SPID3; -#endif - -#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) -extern SPIDriver SPID4; -#endif - -#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) -extern SPIDriver SPID5; -#endif - -#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) -extern SPIDriver SPID6; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void spi_lld_init(void); - void spi_lld_start(SPIDriver *spip); - void spi_lld_stop(SPIDriver *spip); -#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) - void spi_lld_select(SPIDriver *spip); - void spi_lld_unselect(SPIDriver *spip); -#endif - void spi_lld_ignore(SPIDriver *spip, size_t n); - void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); - void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) - void spi_lld_abort(SPIDriver *spip); -#endif - uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SPI */ - -#endif /* HAL_SPI_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv1/hal_spi_lld.h + * @brief STM32 SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef HAL_SPI_LLD_H +#define HAL_SPI_LLD_H + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Circular mode support flag. + */ +#define SPI_SUPPORTS_CIRCULAR TRUE + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI2 driver enable switch. + * @details If set to @p TRUE the support for SPI2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI2 FALSE +#endif + +/** + * @brief SPI3 driver enable switch. + * @details If set to @p TRUE the support for SPI3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI3 FALSE +#endif + +/** + * @brief SPI4 driver enable switch. + * @details If set to @p TRUE the support for SPI4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI4 FALSE +#endif + +/** + * @brief SPI5 driver enable switch. + * @details If set to @p TRUE the support for SPI5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI5 FALSE +#endif + +/** + * @brief SPI6 driver enable switch. + * @details If set to @p TRUE the support for SPI6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI6 FALSE +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI2 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI3 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI4 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI5 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI6 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI DMA error hook. + */ +#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 +#error "SPI4 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 +#error "SPI5 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 +#error "SPI6 not present in the selected device" +#endif + +#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ + !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI6" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI6" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) +#error "SPI4 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) +#error "SPI5 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI6_TX_DMA_STREAM)) +#error "SPI6 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI4 RX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI4 TX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI5 RX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI5 TX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI6 RX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI6 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD +#error "SPI_SELECT_MODE_LLD not supported by this driver" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the SPI driver structure. + */ +#define spi_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /* Receive DMA stream.*/ \ + const stm32_dma_stream_t *dmarx; \ + /* Transmit DMA stream.*/ \ + const stm32_dma_stream_t *dmatx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode + +/** + * @brief Low level fields of the SPI configuration structure. + */ +#define spi_lld_config_fields \ + /* SPI CR1 register initialization data.*/ \ + uint16_t cr1; \ + /* SPI CR2 register initialization data.*/ \ + uint16_t cr2 + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) +extern SPIDriver SPID4; +#endif + +#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) +extern SPIDriver SPID5; +#endif + +#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) +extern SPIDriver SPID6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); +#endif + void spi_lld_ignore(SPIDriver *spip, size_t n); + void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) + void spi_lld_abort(SPIDriver *spip); +#endif + uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* HAL_SPI_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv2/driver.mk b/os/hal/ports/STM32/LLD/SPIv2/driver.mk index 2e1bae4f49..d18ea35c00 100644 --- a/os/hal/ports/STM32/LLD/SPIv2/driver.mk +++ b/os/hal/ports/STM32/LLD/SPIv2/driver.mk @@ -1,13 +1,13 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c -endif -ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c +endif +ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2 diff --git a/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c b/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c index aa437dafbf..bf871ef00a 100644 --- a/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c @@ -1,572 +1,572 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv2/hal_i2s_lld.c - * @brief STM32 I2S subsystem low level driver source. - * - * @addtogroup I2S - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define I2S1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_RX_DMA_STREAM, \ - STM32_SPI1_RX_DMA_CHN) - -#define I2S1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_TX_DMA_STREAM, \ - STM32_SPI1_TX_DMA_CHN) - -#define I2S2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \ - STM32_SPI2_RX_DMA_CHN) - -#define I2S2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \ - STM32_SPI2_TX_DMA_CHN) - -#define I2S3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \ - STM32_SPI3_RX_DMA_CHN) - -#define I2S3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \ - STM32_SPI3_TX_DMA_CHN) - -/* - * Static I2S settings for I2S1. - */ -#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG 0 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 -#endif -#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) -#define STM32_I2S1_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ - SPI_I2SCFGR_I2SCFG_0) -#endif -#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ - -/* - * Static I2S settings for I2S2. - */ -#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG 0 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 -#endif -#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) -#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ - SPI_I2SCFGR_I2SCFG_0) -#endif -#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ - -/* - * Static I2S settings for I2S3. - */ -#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG 0 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 -#endif -#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 -#endif -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) -#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ - SPI_I2SCFGR_I2SCFG_0) -#endif -#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2S1 driver identifier.*/ -#if STM32_I2S_USE_SPI1 || defined(__DOXYGEN__) -I2SDriver I2SD1; -#endif - -/** @brief I2S2 driver identifier.*/ -#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__) -I2SDriver I2SD2; -#endif - -/** @brief I2S3 driver identifier.*/ -#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__) -I2SDriver I2SD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) || \ - STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \ - STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) -/** - * @brief Shared end-of-rx service routine. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) { - - (void)i2sp; - - /* DMA errors handling.*/ -#if defined(STM32_I2S_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2S_DMA_ERROR_HOOK(i2sp); - } -#endif - - /* Callbacks handling, note it is portable code defined in the high - level driver.*/ - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _i2s_isr_full_code(i2sp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _i2s_isr_half_code(i2sp); - } -} -#endif - -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) || \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) -/** - * @brief Shared end-of-tx service routine. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) { - - (void)i2sp; - - /* DMA errors handling.*/ -#if defined(STM32_I2S_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2S_DMA_ERROR_HOOK(i2sp); - } -#endif - - /* Callbacks handling, note it is portable code defined in the high - level driver.*/ - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _i2s_isr_full_code(i2sp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _i2s_isr_half_code(i2sp); - } -} -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2S driver initialization. - * - * @notapi - */ -void i2s_lld_init(void) { - -#if STM32_I2S_USE_SPI1 - i2sObjectInit(&I2SD1); - I2SD1.spi = SPI1; - I2SD1.cfg = STM32_I2S1_CFGR_CFG; - I2SD1.dmarx = NULL; - I2SD1.dmatx = NULL; -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) - I2SD1.rxdmamode = STM32_DMA_CR_CHSEL(I2S1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD1.rxdmamode = 0; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) - I2SD1.txdmamode = STM32_DMA_CR_CHSEL(I2S1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD1.txdmamode = 0; -#endif -#endif - -#if STM32_I2S_USE_SPI2 - i2sObjectInit(&I2SD2); - I2SD2.spi = SPI2; - I2SD2.cfg = STM32_I2S2_CFGR_CFG; - I2SD2.dmarx = NULL; - I2SD2.dmatx = NULL; -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) - I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD2.rxdmamode = 0; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) - I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD2.txdmamode = 0; -#endif -#endif - -#if STM32_I2S_USE_SPI3 - i2sObjectInit(&I2SD3); - I2SD3.spi = SPI3; - I2SD3.cfg = STM32_I2S3_CFGR_CFG; - I2SD3.dmarx = NULL; - I2SD3.dmatx = NULL; -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) - I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD3.rxdmamode = 0; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) - I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | - STM32_DMA_CR_CIRC | - STM32_DMA_CR_HTIE | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#else - I2SD3.txdmamode = 0; -#endif -#endif -} - -/** - * @brief Configures and activates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start(I2SDriver *i2sp) { - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (i2sp->state == I2S_STOP) { - -#if STM32_I2S_USE_SPI1 - if (&I2SD1 == i2sp) { - - /* Enabling I2S unit clock.*/ - rccEnableSPI1(true); - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) - i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI1_RX_DMA_STREAM, - STM32_I2S_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_RXDMAEN; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) - i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI1_TX_DMA_STREAM, - STM32_I2S_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_TXDMAEN; -#endif - } -#endif - -#if STM32_I2S_USE_SPI2 - if (&I2SD2 == i2sp) { - - /* Enabling I2S unit clock.*/ - rccEnableSPI2(true); - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) - i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI2_RX_DMA_STREAM, - STM32_I2S_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_RXDMAEN; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) - i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI2_TX_DMA_STREAM, - STM32_I2S_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_TXDMAEN; -#endif - } -#endif - -#if STM32_I2S_USE_SPI3 - if (&I2SD3 == i2sp) { - - /* Enabling I2S unit clock.*/ - rccEnableSPI3(true); - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) - i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI3_RX_DMA_STREAM, - STM32_I2S_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_RXDMAEN; -#endif -#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) - i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI3_TX_DMA_STREAM, - STM32_I2S_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, - (void *)i2sp); - osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); - - /* CRs settings are done here because those never changes until - the driver is stopped.*/ - i2sp->spi->CR1 = 0; - i2sp->spi->CR2 = SPI_CR2_TXDMAEN; -#endif - } -#endif - } - - /* I2S (re)configuration.*/ - i2sp->spi->I2SPR = i2sp->config->i2spr; - i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD; -} - -/** - * @brief Deactivates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_stop(I2SDriver *i2sp) { - - /* If in ready state then disables the SPI clock.*/ - if (i2sp->state == I2S_READY) { - - /* SPI disable.*/ - i2sp->spi->CR2 = 0; - if (NULL != i2sp->dmarx) { - dmaStreamFreeI(i2sp->dmarx); - i2sp->dmarx = NULL; - } - if (NULL != i2sp->dmatx) { - dmaStreamFreeI(i2sp->dmatx); - i2sp->dmatx = NULL; - } - -#if STM32_I2S_USE_SPI1 - if (&I2SD1 == i2sp) - rccDisableSPI1(); -#endif - -#if STM32_I2S_USE_SPI2 - if (&I2SD2 == i2sp) - rccDisableSPI2(); -#endif - -#if STM32_I2S_USE_SPI3 - if (&I2SD3 == i2sp) - rccDisableSPI3(); -#endif - } -} - -/** - * @brief Starts a I2S data exchange. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start_exchange(I2SDriver *i2sp) { - size_t size = i2sp->config->size; - - /* In 32 bit modes the DMA has to perform double operations because fetches - are always performed using 16 bit accesses. - DATLEN CHLEN SIZE - 00 (16) 0 (16) 16 - 00 (16) 1 (32) 16 - 01 (24) X 32 - 10 (32) X 32 - 11 (NA) X NA - */ - if ((i2sp->config->i2scfgr & SPI_I2SCFGR_DATLEN) != 0) - size *= 2; - - /* RX DMA setup.*/ - if (NULL != i2sp->dmarx) { - dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode); - dmaStreamSetPeripheral(i2sp->dmarx, &i2sp->spi->DR); - dmaStreamSetMemory0(i2sp->dmarx, i2sp->config->rx_buffer); - dmaStreamSetTransactionSize(i2sp->dmarx, size); - dmaStreamEnable(i2sp->dmarx); - } - - /* TX DMA setup.*/ - if (NULL != i2sp->dmatx) { - dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode); - dmaStreamSetPeripheral(i2sp->dmatx, &i2sp->spi->DR); - dmaStreamSetMemory0(i2sp->dmatx, i2sp->config->tx_buffer); - dmaStreamSetTransactionSize(i2sp->dmatx, size); - dmaStreamEnable(i2sp->dmatx); - } - - /* Starting transfer.*/ - i2sp->spi->I2SCFGR |= SPI_I2SCFGR_I2SE; -} - -/** - * @brief Stops the ongoing data exchange. - * @details The ongoing data exchange, if any, is stopped, if the driver - * was not active the function does nothing. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_stop_exchange(I2SDriver *i2sp) { - - /* Stop TX DMA, if enabled.*/ - if (NULL != i2sp->dmatx) { - dmaStreamDisable(i2sp->dmatx); - - /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory - to wait for TXE = 1 and BSY = 0.*/ - while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE) - ; - } - - /* Stop SPI/I2S peripheral.*/ - i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE; - - /* Stop RX DMA, if enabled.*/ - if (NULL != i2sp->dmarx) - dmaStreamDisable(i2sp->dmarx); -} - -#endif /* HAL_USE_I2S */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv2/hal_i2s_lld.c + * @brief STM32 I2S subsystem low level driver source. + * + * @addtogroup I2S + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define I2S1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_RX_DMA_STREAM, \ + STM32_SPI1_RX_DMA_CHN) + +#define I2S1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_TX_DMA_STREAM, \ + STM32_SPI1_TX_DMA_CHN) + +#define I2S2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \ + STM32_SPI2_RX_DMA_CHN) + +#define I2S2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \ + STM32_SPI2_TX_DMA_CHN) + +#define I2S3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \ + STM32_SPI3_RX_DMA_CHN) + +#define I2S3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \ + STM32_SPI3_TX_DMA_CHN) + +/* + * Static I2S settings for I2S1. + */ +#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG 0 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 +#endif +#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) +#define STM32_I2S1_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ + SPI_I2SCFGR_I2SCFG_0) +#endif +#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */ + +/* + * Static I2S settings for I2S2. + */ +#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG 0 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 +#endif +#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) +#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ + SPI_I2SCFGR_I2SCFG_0) +#endif +#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */ + +/* + * Static I2S settings for I2S3. + */ +#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG 0 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0 +#endif +#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1 +#endif +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) +#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \ + SPI_I2SCFGR_I2SCFG_0) +#endif +#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2S1 driver identifier.*/ +#if STM32_I2S_USE_SPI1 || defined(__DOXYGEN__) +I2SDriver I2SD1; +#endif + +/** @brief I2S2 driver identifier.*/ +#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__) +I2SDriver I2SD2; +#endif + +/** @brief I2S3 driver identifier.*/ +#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__) +I2SDriver I2SD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) || \ + STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \ + STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) +/** + * @brief Shared end-of-rx service routine. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) { + + (void)i2sp; + + /* DMA errors handling.*/ +#if defined(STM32_I2S_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2S_DMA_ERROR_HOOK(i2sp); + } +#endif + + /* Callbacks handling, note it is portable code defined in the high + level driver.*/ + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _i2s_isr_full_code(i2sp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _i2s_isr_half_code(i2sp); + } +} +#endif + +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) || \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) +/** + * @brief Shared end-of-tx service routine. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) { + + (void)i2sp; + + /* DMA errors handling.*/ +#if defined(STM32_I2S_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2S_DMA_ERROR_HOOK(i2sp); + } +#endif + + /* Callbacks handling, note it is portable code defined in the high + level driver.*/ + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _i2s_isr_full_code(i2sp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _i2s_isr_half_code(i2sp); + } +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2S driver initialization. + * + * @notapi + */ +void i2s_lld_init(void) { + +#if STM32_I2S_USE_SPI1 + i2sObjectInit(&I2SD1); + I2SD1.spi = SPI1; + I2SD1.cfg = STM32_I2S1_CFGR_CFG; + I2SD1.dmarx = NULL; + I2SD1.dmatx = NULL; +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) + I2SD1.rxdmamode = STM32_DMA_CR_CHSEL(I2S1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD1.rxdmamode = 0; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) + I2SD1.txdmamode = STM32_DMA_CR_CHSEL(I2S1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD1.txdmamode = 0; +#endif +#endif + +#if STM32_I2S_USE_SPI2 + i2sObjectInit(&I2SD2); + I2SD2.spi = SPI2; + I2SD2.cfg = STM32_I2S2_CFGR_CFG; + I2SD2.dmarx = NULL; + I2SD2.dmatx = NULL; +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) + I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD2.rxdmamode = 0; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) + I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD2.txdmamode = 0; +#endif +#endif + +#if STM32_I2S_USE_SPI3 + i2sObjectInit(&I2SD3); + I2SD3.spi = SPI3; + I2SD3.cfg = STM32_I2S3_CFGR_CFG; + I2SD3.dmarx = NULL; + I2SD3.dmatx = NULL; +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) + I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD3.rxdmamode = 0; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) + I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | + STM32_DMA_CR_CIRC | + STM32_DMA_CR_HTIE | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#else + I2SD3.txdmamode = 0; +#endif +#endif +} + +/** + * @brief Configures and activates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start(I2SDriver *i2sp) { + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (i2sp->state == I2S_STOP) { + +#if STM32_I2S_USE_SPI1 + if (&I2SD1 == i2sp) { + + /* Enabling I2S unit clock.*/ + rccEnableSPI1(true); + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) + i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI1_RX_DMA_STREAM, + STM32_I2S_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_RXDMAEN; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) + i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI1_TX_DMA_STREAM, + STM32_I2S_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_TXDMAEN; +#endif + } +#endif + +#if STM32_I2S_USE_SPI2 + if (&I2SD2 == i2sp) { + + /* Enabling I2S unit clock.*/ + rccEnableSPI2(true); + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) + i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI2_RX_DMA_STREAM, + STM32_I2S_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_RXDMAEN; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) + i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI2_TX_DMA_STREAM, + STM32_I2S_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_TXDMAEN; +#endif + } +#endif + +#if STM32_I2S_USE_SPI3 + if (&I2SD3 == i2sp) { + + /* Enabling I2S unit clock.*/ + rccEnableSPI3(true); + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) + i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI3_RX_DMA_STREAM, + STM32_I2S_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_RXDMAEN; +#endif +#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) + i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI3_TX_DMA_STREAM, + STM32_I2S_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt, + (void *)i2sp); + osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream"); + + /* CRs settings are done here because those never changes until + the driver is stopped.*/ + i2sp->spi->CR1 = 0; + i2sp->spi->CR2 = SPI_CR2_TXDMAEN; +#endif + } +#endif + } + + /* I2S (re)configuration.*/ + i2sp->spi->I2SPR = i2sp->config->i2spr; + i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD; +} + +/** + * @brief Deactivates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_stop(I2SDriver *i2sp) { + + /* If in ready state then disables the SPI clock.*/ + if (i2sp->state == I2S_READY) { + + /* SPI disable.*/ + i2sp->spi->CR2 = 0; + if (NULL != i2sp->dmarx) { + dmaStreamFreeI(i2sp->dmarx); + i2sp->dmarx = NULL; + } + if (NULL != i2sp->dmatx) { + dmaStreamFreeI(i2sp->dmatx); + i2sp->dmatx = NULL; + } + +#if STM32_I2S_USE_SPI1 + if (&I2SD1 == i2sp) + rccDisableSPI1(); +#endif + +#if STM32_I2S_USE_SPI2 + if (&I2SD2 == i2sp) + rccDisableSPI2(); +#endif + +#if STM32_I2S_USE_SPI3 + if (&I2SD3 == i2sp) + rccDisableSPI3(); +#endif + } +} + +/** + * @brief Starts a I2S data exchange. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start_exchange(I2SDriver *i2sp) { + size_t size = i2sp->config->size; + + /* In 32 bit modes the DMA has to perform double operations because fetches + are always performed using 16 bit accesses. + DATLEN CHLEN SIZE + 00 (16) 0 (16) 16 + 00 (16) 1 (32) 16 + 01 (24) X 32 + 10 (32) X 32 + 11 (NA) X NA + */ + if ((i2sp->config->i2scfgr & SPI_I2SCFGR_DATLEN) != 0) + size *= 2; + + /* RX DMA setup.*/ + if (NULL != i2sp->dmarx) { + dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode); + dmaStreamSetPeripheral(i2sp->dmarx, &i2sp->spi->DR); + dmaStreamSetMemory0(i2sp->dmarx, i2sp->config->rx_buffer); + dmaStreamSetTransactionSize(i2sp->dmarx, size); + dmaStreamEnable(i2sp->dmarx); + } + + /* TX DMA setup.*/ + if (NULL != i2sp->dmatx) { + dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode); + dmaStreamSetPeripheral(i2sp->dmatx, &i2sp->spi->DR); + dmaStreamSetMemory0(i2sp->dmatx, i2sp->config->tx_buffer); + dmaStreamSetTransactionSize(i2sp->dmatx, size); + dmaStreamEnable(i2sp->dmatx); + } + + /* Starting transfer.*/ + i2sp->spi->I2SCFGR |= SPI_I2SCFGR_I2SE; +} + +/** + * @brief Stops the ongoing data exchange. + * @details The ongoing data exchange, if any, is stopped, if the driver + * was not active the function does nothing. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_stop_exchange(I2SDriver *i2sp) { + + /* Stop TX DMA, if enabled.*/ + if (NULL != i2sp->dmatx) { + dmaStreamDisable(i2sp->dmatx); + + /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory + to wait for TXE = 1 and BSY = 0.*/ + while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE) + ; + } + + /* Stop SPI/I2S peripheral.*/ + i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE; + + /* Stop RX DMA, if enabled.*/ + if (NULL != i2sp->dmarx) + dmaStreamDisable(i2sp->dmarx); +} + +#endif /* HAL_USE_I2S */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h b/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h index acf92e1d8f..393163c5e4 100644 --- a/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h +++ b/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h @@ -1,371 +1,371 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv2/hal_i2s_lld.h - * @brief STM32 I2S subsystem low level driver header. - * - * @addtogroup I2S - * @{ - */ - -#ifndef HAL_I2S_LLD_H -#define HAL_I2S_LLD_H - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Static I2S modes - * @{ - */ -#define STM32_I2S_MODE_SLAVE 0 -#define STM32_I2S_MODE_MASTER 1 -#define STM32_I2S_MODE_RX 2 -#define STM32_I2S_MODE_TX 4 -#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \ - STM32_I2S_MODE_TX) -/** @} */ - -/** - * @name Mode checks - * @{ - */ -#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER) -#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX) -#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2S1 driver enable switch. - * @details If set to @p TRUE the support for I2S1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_I2S_USE_SPI1 FALSE -#endif - -/** - * @brief I2S2 driver enable switch. - * @details If set to @p TRUE the support for I2S2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_I2S_USE_SPI2 FALSE -#endif - -/** - * @brief I2S3 driver enable switch. - * @details If set to @p TRUE the support for I2S3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_I2S_USE_SPI3 FALSE -#endif - -/** - * @brief I2S1 mode. - */ -#if !defined(STM32_I2S_SPI1_MODE) || defined(__DOXYGEN__) -#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ - STM32_I2S_MODE_RX) -#endif - -/** - * @brief I2S2 mode. - */ -#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__) -#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \ - STM32_I2S_MODE_RX) -#endif - -/** - * @brief I2S3 mode. - */ -#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) -#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \ - STM32_I2S_MODE_RX) -#endif - -/** - * @brief I2S1 interrupt priority level setting. - */ -#if !defined(STM32_I2S_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S2 interrupt priority level setting. - */ -#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S3 interrupt priority level setting. - */ -#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S3 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S DMA error hook. - */ -#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_I2S_USE_SPI1 && !STM32_SPI1_SUPPORTS_I2S -#error "SPI1 does not support I2S mode" -#endif - -#if STM32_I2S_USE_SPI2 && !STM32_SPI2_SUPPORTS_I2S -#error "SPI2 does not support I2S mode" -#endif - -#if STM32_I2S_USE_SPI3 && !STM32_SPI3_SUPPORTS_I2S -#error "SPI3 does not support I2S mode" -#endif - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) && \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) -#error "I2S1 RX and TX mode not supported in this driver implementation" -#endif - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) && \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) -#error "I2S2 RX and TX mode not supported in this driver implementation" -#endif - -#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) && \ - STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) -#error "I2S3 RX and TX mode not supported in this driver implementation" -#endif - -#if STM32_I2S_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if !STM32_I2S_USE_SPI1 && !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3 -#error "I2S driver activated but no SPI peripheral assigned" -#endif - -#if STM32_I2S_USE_SPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_I2S_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2S_USE_SPI1 && (!defined(STM32_I2S_SPI1_RX_DMA_STREAM) || \ - !defined(STM32_I2S_SPI1_TX_DMA_STREAM)) -#error "SPI1 DMA streams not defined" -#endif - -#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \ - !defined(STM32_I2S_SPI2_TX_DMA_STREAM)) -#error "SPI2 DMA streams not defined" -#endif - -#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \ - !defined(STM32_I2S_SPI3_TX_DMA_STREAM)) -#error "SPI3 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2S_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 RX" -#endif - -#if STM32_I2S_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 TX" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 RX" -#endif - -#if STM32_I2S_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 TX" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 RX" -#endif - -#if STM32_I2S_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the I2S driver structure. - */ -#define i2s_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /* Calculated part of the I2SCFGR register.*/ \ - uint16_t cfg; \ - /* Receive DMA stream or @p NULL.*/ \ - const stm32_dma_stream_t *dmarx; \ - /* Transmit DMA stream or @p NULL.*/ \ - const stm32_dma_stream_t *dmatx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode - -/** - * @brief Low level fields of the I2S configuration structure. - */ -#define i2s_lld_config_fields \ - /* Configuration of the I2SCFGR register. \ - NOTE: See the STM32 reference manual, this register is used for \ - the I2S configuration, the following bits must not be \ - specified because handled directly by the driver: \ - - I2SMOD \ - - I2SE \ - - I2SCFG \ - */ \ - int16_t i2scfgr; \ - /* Configuration of the I2SPR register. \ - NOTE: See the STM32 reference manual, this register is used for \ - the I2S clock setup.*/ \ - int16_t i2spr - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_I2S_USE_SPI1 && !defined(__DOXYGEN__) -extern I2SDriver I2SD1; -#endif - -#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__) -extern I2SDriver I2SD2; -#endif - -#if STM32_I2S_USE_SPI3 && !defined(__DOXYGEN__) -extern I2SDriver I2SD3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void i2s_lld_init(void); - void i2s_lld_start(I2SDriver *i2sp); - void i2s_lld_stop(I2SDriver *i2sp); - void i2s_lld_start_exchange(I2SDriver *i2sp); - void i2s_lld_stop_exchange(I2SDriver *i2sp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2S */ - -#endif /* HAL_I2S_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv2/hal_i2s_lld.h + * @brief STM32 I2S subsystem low level driver header. + * + * @addtogroup I2S + * @{ + */ + +#ifndef HAL_I2S_LLD_H +#define HAL_I2S_LLD_H + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Static I2S modes + * @{ + */ +#define STM32_I2S_MODE_SLAVE 0 +#define STM32_I2S_MODE_MASTER 1 +#define STM32_I2S_MODE_RX 2 +#define STM32_I2S_MODE_TX 4 +#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \ + STM32_I2S_MODE_TX) +/** @} */ + +/** + * @name Mode checks + * @{ + */ +#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER) +#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX) +#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2S1 driver enable switch. + * @details If set to @p TRUE the support for I2S1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_I2S_USE_SPI1 FALSE +#endif + +/** + * @brief I2S2 driver enable switch. + * @details If set to @p TRUE the support for I2S2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_I2S_USE_SPI2 FALSE +#endif + +/** + * @brief I2S3 driver enable switch. + * @details If set to @p TRUE the support for I2S3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_I2S_USE_SPI3 FALSE +#endif + +/** + * @brief I2S1 mode. + */ +#if !defined(STM32_I2S_SPI1_MODE) || defined(__DOXYGEN__) +#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#endif + +/** + * @brief I2S2 mode. + */ +#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__) +#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#endif + +/** + * @brief I2S3 mode. + */ +#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__) +#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#endif + +/** + * @brief I2S1 interrupt priority level setting. + */ +#if !defined(STM32_I2S_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S2 interrupt priority level setting. + */ +#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S3 interrupt priority level setting. + */ +#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S3 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S DMA error hook. + */ +#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_I2S_USE_SPI1 && !STM32_SPI1_SUPPORTS_I2S +#error "SPI1 does not support I2S mode" +#endif + +#if STM32_I2S_USE_SPI2 && !STM32_SPI2_SUPPORTS_I2S +#error "SPI2 does not support I2S mode" +#endif + +#if STM32_I2S_USE_SPI3 && !STM32_SPI3_SUPPORTS_I2S +#error "SPI3 does not support I2S mode" +#endif + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) && \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) +#error "I2S1 RX and TX mode not supported in this driver implementation" +#endif + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) && \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) +#error "I2S2 RX and TX mode not supported in this driver implementation" +#endif + +#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) && \ + STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) +#error "I2S3 RX and TX mode not supported in this driver implementation" +#endif + +#if STM32_I2S_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if !STM32_I2S_USE_SPI1 && !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3 +#error "I2S driver activated but no SPI peripheral assigned" +#endif + +#if STM32_I2S_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_I2S_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2S_USE_SPI1 && (!defined(STM32_I2S_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_I2S_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_I2S_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_I2S_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2S_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_I2S_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_I2S_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_I2S_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the I2S driver structure. + */ +#define i2s_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /* Calculated part of the I2SCFGR register.*/ \ + uint16_t cfg; \ + /* Receive DMA stream or @p NULL.*/ \ + const stm32_dma_stream_t *dmarx; \ + /* Transmit DMA stream or @p NULL.*/ \ + const stm32_dma_stream_t *dmatx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode + +/** + * @brief Low level fields of the I2S configuration structure. + */ +#define i2s_lld_config_fields \ + /* Configuration of the I2SCFGR register. \ + NOTE: See the STM32 reference manual, this register is used for \ + the I2S configuration, the following bits must not be \ + specified because handled directly by the driver: \ + - I2SMOD \ + - I2SE \ + - I2SCFG \ + */ \ + int16_t i2scfgr; \ + /* Configuration of the I2SPR register. \ + NOTE: See the STM32 reference manual, this register is used for \ + the I2S clock setup.*/ \ + int16_t i2spr + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_I2S_USE_SPI1 && !defined(__DOXYGEN__) +extern I2SDriver I2SD1; +#endif + +#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__) +extern I2SDriver I2SD2; +#endif + +#if STM32_I2S_USE_SPI3 && !defined(__DOXYGEN__) +extern I2SDriver I2SD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void i2s_lld_init(void); + void i2s_lld_start(I2SDriver *i2sp); + void i2s_lld_stop(I2SDriver *i2sp); + void i2s_lld_start_exchange(I2SDriver *i2sp); + void i2s_lld_stop_exchange(I2SDriver *i2sp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2S */ + +#endif /* HAL_I2S_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c index 02bc9a07bc..69d54d99ee 100644 --- a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c @@ -1,720 +1,720 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv2/hal_spi_lld.c - * @brief STM32 SPI subsystem low level driver source. - * - * @addtogroup SPI - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SPI1_RX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ - STM32_SPI1_RX_DMA_CHN) - -#define SPI1_TX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ - STM32_SPI1_TX_DMA_CHN) - -#define SPI2_RX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ - STM32_SPI2_RX_DMA_CHN) - -#define SPI2_TX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ - STM32_SPI2_TX_DMA_CHN) - -#define SPI3_RX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ - STM32_SPI3_RX_DMA_CHN) - -#define SPI3_TX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ - STM32_SPI3_TX_DMA_CHN) - -#define SPI4_RX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_RX_DMA_STREAM, \ - STM32_SPI4_RX_DMA_CHN) - -#define SPI4_TX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_TX_DMA_STREAM, \ - STM32_SPI4_TX_DMA_CHN) - -#define SPI5_RX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_RX_DMA_STREAM, \ - STM32_SPI5_RX_DMA_CHN) - -#define SPI5_TX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_TX_DMA_STREAM, \ - STM32_SPI5_TX_DMA_CHN) - -#define SPI6_RX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_RX_DMA_STREAM, \ - STM32_SPI6_RX_DMA_CHN) - -#define SPI6_TX_DMA_STREAM \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_TX_DMA_STREAM, \ - STM32_SPI6_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SPI1 driver identifier.*/ -#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) -SPIDriver SPID1; -#endif - -/** @brief SPI2 driver identifier.*/ -#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) -SPIDriver SPID2; -#endif - -/** @brief SPI3 driver identifier.*/ -#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) -SPIDriver SPID3; -#endif - -/** @brief SPI4 driver identifier.*/ -#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) -SPIDriver SPID4; -#endif - -/** @brief SPI5 driver identifier.*/ -#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) -SPIDriver SPID5; -#endif - -/** @brief SPI6 driver identifier.*/ -#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) -SPIDriver SPID6; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint16_t dummytx = 0xFFFFU; -static uint16_t dummyrx; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared end-of-rx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)flags; -#endif - - if (spip->config->circular) { - if ((flags & STM32_DMA_ISR_HTIF) != 0U) { - /* Half buffer interrupt.*/ - _spi_isr_half_code(spip); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0U) { - /* End buffer interrupt.*/ - _spi_isr_full_code(spip); - } - } - else { - /* Stopping DMAs.*/ - dmaStreamDisable(spip->dmatx); - dmaStreamDisable(spip->dmarx); - - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); - } -} - -/** - * @brief Shared end-of-tx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - (void)spip; - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)spip; - (void)flags; -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SPI driver initialization. - * - * @notapi - */ -void spi_lld_init(void) { - -#if STM32_SPI_USE_SPI1 - spiObjectInit(&SPID1); - SPID1.spi = SPI1; - SPID1.dmarx = NULL; - SPID1.dmatx = NULL; - SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI2 - spiObjectInit(&SPID2); - SPID2.spi = SPI2; - SPID2.dmarx = NULL; - SPID2.dmatx = NULL; - SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI3 - spiObjectInit(&SPID3); - SPID3.spi = SPI3; - SPID3.dmarx = NULL; - SPID3.dmatx = NULL; - SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI4 - spiObjectInit(&SPID4); - SPID4.spi = SPI4; - SPID4.dmarx = NULL; - SPID4.dmatx = NULL; - SPID4.rxdmamode = STM32_DMA_CR_CHSEL(SPI4_RX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID4.txdmamode = STM32_DMA_CR_CHSEL(SPI4_TX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI5 - spiObjectInit(&SPID5); - SPID5.spi = SPI5; - SPID5.dmarx = NULL; - SPID5.dmatx = NULL; - SPID5.rxdmamode = STM32_DMA_CR_CHSEL(SPI5_RX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID5.txdmamode = STM32_DMA_CR_CHSEL(SPI5_TX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI6 - spiObjectInit(&SPID6); - SPID6.spi = SPI6; - SPID6.dmarx = NULL; - SPID6.dmatx = NULL; - SPID6.rxdmamode = STM32_DMA_CR_CHSEL(SPI6_RX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID6.txdmamode = STM32_DMA_CR_CHSEL(SPI6_TX_DMA_STREAM) | - STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_start(SPIDriver *spip) { - uint32_t ds; - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (spip->state == SPI_STOP) { -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI1(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI1_RX); - dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI1_TX); -#endif - } -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI2(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI2_RX); - dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI2_TX); -#endif - } -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI3(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI3_RX); - dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI3_TX); -#endif - } -#endif -#if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI4(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI4_RX); - dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI4_TX); -#endif - } -#endif -#if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI5(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI5_RX); - dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI5_TX); -#endif - } -#endif -#if STM32_SPI_USE_SPI6 - if (&SPID6 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); - rccEnableSPI6(true); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI6_RX); - dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI6_TX); -#endif - } -#endif - - /* DMA setup.*/ - dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); - dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); - } - - /* Configuration-specific DMA setup.*/ - ds = spip->config->cr2 & SPI_CR2_DS; - if (!ds || (ds <= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0))) { - /* Frame width is 8 bits or smaller.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - } - else { - /* Frame width is larger than 8 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - - if (spip->config->circular) { - spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - } - else { - spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - } - - /* SPI setup and enable.*/ - spip->spi->CR1 &= ~SPI_CR1_SPE; - spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR; - spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE | - SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; - spip->spi->CR1 |= SPI_CR1_SPE; -} - -/** - * @brief Deactivates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_stop(SPIDriver *spip) { - - /* If in ready state then disables the SPI clock.*/ - if (spip->state == SPI_READY) { - - /* SPI disable.*/ - spip->spi->CR1 &= ~SPI_CR1_SPE; - spip->spi->CR1 = 0; - spip->spi->CR2 = 0; - dmaStreamFreeI(spip->dmarx); - dmaStreamFreeI(spip->dmatx); - spip->dmarx = NULL; - spip->dmatx = NULL; - -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) - rccDisableSPI1(); -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) - rccDisableSPI2(); -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) - rccDisableSPI3(); -#endif -#if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) - rccDisableSPI4(); -#endif -#if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) - rccDisableSPI5(); -#endif -#if STM32_SPI_USE_SPI6 - if (&SPID6 == spip) - rccDisableSPI6(); -#endif - } -} - -#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_select(SPIDriver *spip) { - - /* No implementation on STM32.*/ -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_unselect(SPIDriver *spip) { - - /* No implementation on STM32.*/ -} -#endif - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @notapi - */ -void spi_lld_ignore(SPIDriver *spip, size_t n) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) -/** - * @brief Aborts the ongoing SPI operation, if any. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_abort(SPIDriver *spip) { - - /* Stopping DMAs.*/ - dmaStreamDisable(spip->dmatx); - dmaStreamDisable(spip->dmarx); -} -#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ - -/** - * @brief Exchanges one frame using a polled wait. - * @details This synchronous function exchanges one frame using a polled - * synchronization method. This function is useful when exchanging - * small amount of data on high speed channels, usually in this - * situation is much more efficient just wait for completion using - * polling than suspending the thread waiting for an interrupt. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] frame the data frame to send over the SPI bus - * @return The received data frame from the SPI bus. - */ -uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { - - /* - * Data register must be accessed with the appropriate data size. - * Byte size access (uint8_t *) for transactions that are <= 8-bit. - * Halfword size access (uint16_t) for transactions that are <= 8-bit. - */ - if ((spip->config->cr2 & SPI_CR2_DS) <= (SPI_CR2_DS_2 | - SPI_CR2_DS_1 | - SPI_CR2_DS_0)) { - volatile uint8_t *spidr = (volatile uint8_t *)&spip->spi->DR; - *spidr = (uint8_t)frame; - while ((spip->spi->SR & SPI_SR_RXNE) == 0) - ; - return (uint16_t)*spidr; - } - else { - spip->spi->DR = frame; - while ((spip->spi->SR & SPI_SR_RXNE) == 0) - ; - return spip->spi->DR; - } -} - -#endif /* HAL_USE_SPI */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv2/hal_spi_lld.c + * @brief STM32 SPI subsystem low level driver source. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SPI1_RX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ + STM32_SPI1_RX_DMA_CHN) + +#define SPI1_TX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ + STM32_SPI1_TX_DMA_CHN) + +#define SPI2_RX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ + STM32_SPI2_RX_DMA_CHN) + +#define SPI2_TX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ + STM32_SPI2_TX_DMA_CHN) + +#define SPI3_RX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ + STM32_SPI3_RX_DMA_CHN) + +#define SPI3_TX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ + STM32_SPI3_TX_DMA_CHN) + +#define SPI4_RX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_RX_DMA_STREAM, \ + STM32_SPI4_RX_DMA_CHN) + +#define SPI4_TX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_TX_DMA_STREAM, \ + STM32_SPI4_TX_DMA_CHN) + +#define SPI5_RX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_RX_DMA_STREAM, \ + STM32_SPI5_RX_DMA_CHN) + +#define SPI5_TX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_TX_DMA_STREAM, \ + STM32_SPI5_TX_DMA_CHN) + +#define SPI6_RX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_RX_DMA_STREAM, \ + STM32_SPI6_RX_DMA_CHN) + +#define SPI6_TX_DMA_STREAM \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_TX_DMA_STREAM, \ + STM32_SPI6_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SPI1 driver identifier.*/ +#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/** @brief SPI2 driver identifier.*/ +#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/** @brief SPI3 driver identifier.*/ +#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) +SPIDriver SPID3; +#endif + +/** @brief SPI4 driver identifier.*/ +#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) +SPIDriver SPID4; +#endif + +/** @brief SPI5 driver identifier.*/ +#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) +SPIDriver SPID5; +#endif + +/** @brief SPI6 driver identifier.*/ +#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) +SPIDriver SPID6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint16_t dummytx = 0xFFFFU; +static uint16_t dummyrx; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif + + if (spip->config->circular) { + if ((flags & STM32_DMA_ISR_HTIF) != 0U) { + /* Half buffer interrupt.*/ + _spi_isr_half_code(spip); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0U) { + /* End buffer interrupt.*/ + _spi_isr_full_code(spip); + } + } + else { + /* Stopping DMAs.*/ + dmaStreamDisable(spip->dmatx); + dmaStreamDisable(spip->dmarx); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); + } +} + +/** + * @brief Shared end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { + +#if STM32_SPI_USE_SPI1 + spiObjectInit(&SPID1); + SPID1.spi = SPI1; + SPID1.dmarx = NULL; + SPID1.dmatx = NULL; + SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI2 + spiObjectInit(&SPID2); + SPID2.spi = SPI2; + SPID2.dmarx = NULL; + SPID2.dmatx = NULL; + SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI3 + spiObjectInit(&SPID3); + SPID3.spi = SPI3; + SPID3.dmarx = NULL; + SPID3.dmatx = NULL; + SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI4 + spiObjectInit(&SPID4); + SPID4.spi = SPI4; + SPID4.dmarx = NULL; + SPID4.dmatx = NULL; + SPID4.rxdmamode = STM32_DMA_CR_CHSEL(SPI4_RX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID4.txdmamode = STM32_DMA_CR_CHSEL(SPI4_TX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI5 + spiObjectInit(&SPID5); + SPID5.spi = SPI5; + SPID5.dmarx = NULL; + SPID5.dmatx = NULL; + SPID5.rxdmamode = STM32_DMA_CR_CHSEL(SPI5_RX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID5.txdmamode = STM32_DMA_CR_CHSEL(SPI5_TX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI6 + spiObjectInit(&SPID6); + SPID6.spi = SPI6; + SPID6.dmarx = NULL; + SPID6.dmatx = NULL; + SPID6.rxdmamode = STM32_DMA_CR_CHSEL(SPI6_RX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID6.txdmamode = STM32_DMA_CR_CHSEL(SPI6_TX_DMA_STREAM) | + STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_start(SPIDriver *spip) { + uint32_t ds; + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (spip->state == SPI_STOP) { +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI1(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI1_RX); + dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI1_TX); +#endif + } +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI2(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI2_RX); + dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI2_TX); +#endif + } +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI3(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI3_RX); + dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI3_TX); +#endif + } +#endif +#if STM32_SPI_USE_SPI4 + if (&SPID4 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI4(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI4_RX); + dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI4_TX); +#endif + } +#endif +#if STM32_SPI_USE_SPI5 + if (&SPID5 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI5(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI5_RX); + dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI5_TX); +#endif + } +#endif +#if STM32_SPI_USE_SPI6 + if (&SPID6 == spip) { + spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); + spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + rccEnableSPI6(true); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI6_RX); + dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI6_TX); +#endif + } +#endif + + /* DMA setup.*/ + dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); + dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); + } + + /* Configuration-specific DMA setup.*/ + ds = spip->config->cr2 & SPI_CR2_DS; + if (!ds || (ds <= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0))) { + /* Frame width is 8 bits or smaller.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + } + else { + /* Frame width is larger than 8 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + + if (spip->config->circular) { + spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + else { + spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + + /* SPI setup and enable.*/ + spip->spi->CR1 &= ~SPI_CR1_SPE; + spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR; + spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE | + SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; + spip->spi->CR1 |= SPI_CR1_SPE; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->state == SPI_READY) { + + /* SPI disable.*/ + spip->spi->CR1 &= ~SPI_CR1_SPE; + spip->spi->CR1 = 0; + spip->spi->CR2 = 0; + dmaStreamFreeI(spip->dmarx); + dmaStreamFreeI(spip->dmatx); + spip->dmarx = NULL; + spip->dmatx = NULL; + +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) + rccDisableSPI1(); +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) + rccDisableSPI2(); +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) + rccDisableSPI3(); +#endif +#if STM32_SPI_USE_SPI4 + if (&SPID4 == spip) + rccDisableSPI4(); +#endif +#if STM32_SPI_USE_SPI5 + if (&SPID5 == spip) + rccDisableSPI5(); +#endif +#if STM32_SPI_USE_SPI6 + if (&SPID6 == spip) + rccDisableSPI6(); +#endif + } +} + +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + /* No implementation on STM32.*/ +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + /* No implementation on STM32.*/ +} +#endif + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @notapi + */ +void spi_lld_ignore(SPIDriver *spip, size_t n) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) +/** + * @brief Aborts the ongoing SPI operation, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_abort(SPIDriver *spip) { + + /* Stopping DMAs.*/ + dmaStreamDisable(spip->dmatx); + dmaStreamDisable(spip->dmarx); +} +#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { + + /* + * Data register must be accessed with the appropriate data size. + * Byte size access (uint8_t *) for transactions that are <= 8-bit. + * Halfword size access (uint16_t) for transactions that are <= 8-bit. + */ + if ((spip->config->cr2 & SPI_CR2_DS) <= (SPI_CR2_DS_2 | + SPI_CR2_DS_1 | + SPI_CR2_DS_0)) { + volatile uint8_t *spidr = (volatile uint8_t *)&spip->spi->DR; + *spidr = (uint8_t)frame; + while ((spip->spi->SR & SPI_SR_RXNE) == 0) + ; + return (uint16_t)*spidr; + } + else { + spip->spi->DR = frame; + while ((spip->spi->SR & SPI_SR_RXNE) == 0) + ; + return spip->spi->DR; + } +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h index ec3374d99e..309f94a54f 100644 --- a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h +++ b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h @@ -1,557 +1,557 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv2/hal_spi_lld.h - * @brief STM32 SPI subsystem low level driver header. - * - * @addtogroup SPI - * @{ - */ - -#ifndef HAL_SPI_LLD_H -#define HAL_SPI_LLD_H - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Circular mode support flag. - */ -#define SPI_SUPPORTS_CIRCULAR TRUE - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SPI1 driver enable switch. - * @details If set to @p TRUE the support for SPI1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI1 FALSE -#endif - -/** - * @brief SPI2 driver enable switch. - * @details If set to @p TRUE the support for SPI2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI2 FALSE -#endif - -/** - * @brief SPI3 driver enable switch. - * @details If set to @p TRUE the support for SPI3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI3 FALSE -#endif - -/** - * @brief SPI4 driver enable switch. - * @details If set to @p TRUE the support for SPI4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI4 FALSE -#endif - -/** - * @brief SPI5 driver enable switch. - * @details If set to @p TRUE the support for SPI5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI5 FALSE -#endif - -/** - * @brief SPI6 driver enable switch. - * @details If set to @p TRUE the support for SPI6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI6 FALSE -#endif - -/** - * @brief SPI1 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI2 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI3 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI4 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI4_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI5 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI5_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI6 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI6_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI4_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI5 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI5_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI6 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI6_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI DMA error hook. - */ -#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 -#error "SPI4 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 -#error "SPI5 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 -#error "SPI6 not present in the selected device" -#endif - -#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ - !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 -#error "SPI driver activated but no SPI peripheral assigned" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI4" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI5" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI6" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI4" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI5" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI6" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) -#error "SPI1 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) -#error "SPI2 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) -#error "SPI3 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) -#error "SPI4 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) -#error "SPI5 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI6_TX_DMA_STREAM)) -#error "SPI6 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI1 RX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI1 TX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI2 RX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI2 TX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI3 RX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI3 TX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI4 RX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI4 TX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI5 RX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI5 TX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI6 RX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to SPI6 TX" -#endif - -/* Devices without DMAMUX require an additional check.*/ -#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 RX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 TX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 RX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 TX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 RX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 TX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI4 RX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI4 TX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI5 RX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI5 TX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI6 RX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI6 TX" -#endif - -#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD -#error "SPI_SELECT_MODE_LLD not supported by this driver" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the SPI driver structure. - */ -#define spi_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /* Receive DMA stream.*/ \ - const stm32_dma_stream_t *dmarx; \ - /* Transmit DMA stream.*/ \ - const stm32_dma_stream_t *dmatx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode - -/** - * @brief Low level fields of the SPI configuration structure. - */ -#define spi_lld_config_fields \ - /* SPI CR1 register initialization data.*/ \ - uint16_t cr1; \ - /* SPI CR2 register initialization data.*/ \ - uint16_t cr2 - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) -extern SPIDriver SPID1; -#endif - -#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) -extern SPIDriver SPID2; -#endif - -#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) -extern SPIDriver SPID3; -#endif - -#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) -extern SPIDriver SPID4; -#endif - -#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) -extern SPIDriver SPID5; -#endif - -#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) -extern SPIDriver SPID6; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void spi_lld_init(void); - void spi_lld_start(SPIDriver *spip); - void spi_lld_stop(SPIDriver *spip); -#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) - void spi_lld_select(SPIDriver *spip); - void spi_lld_unselect(SPIDriver *spip); -#endif - void spi_lld_ignore(SPIDriver *spip, size_t n); - void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); - void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) - void spi_lld_abort(SPIDriver *spip); -#endif - uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SPI */ - -#endif /* HAL_SPI_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv2/hal_spi_lld.h + * @brief STM32 SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef HAL_SPI_LLD_H +#define HAL_SPI_LLD_H + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Circular mode support flag. + */ +#define SPI_SUPPORTS_CIRCULAR TRUE + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI2 driver enable switch. + * @details If set to @p TRUE the support for SPI2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI2 FALSE +#endif + +/** + * @brief SPI3 driver enable switch. + * @details If set to @p TRUE the support for SPI3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI3 FALSE +#endif + +/** + * @brief SPI4 driver enable switch. + * @details If set to @p TRUE the support for SPI4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI4 FALSE +#endif + +/** + * @brief SPI5 driver enable switch. + * @details If set to @p TRUE the support for SPI5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI5 FALSE +#endif + +/** + * @brief SPI6 driver enable switch. + * @details If set to @p TRUE the support for SPI6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI6 FALSE +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI2 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI3 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI4 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI5 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI6 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI DMA error hook. + */ +#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 +#error "SPI4 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 +#error "SPI5 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 +#error "SPI6 not present in the selected device" +#endif + +#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ + !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI6" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI6" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) +#error "SPI4 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) +#error "SPI5 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI6_TX_DMA_STREAM)) +#error "SPI6 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI3 TX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI4 RX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI4 TX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI5 RX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI5 TX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI6 RX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI6 TX" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI4 RX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI4 TX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI5 RX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI5 TX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI6 RX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI6 TX" +#endif + +#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD +#error "SPI_SELECT_MODE_LLD not supported by this driver" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the SPI driver structure. + */ +#define spi_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /* Receive DMA stream.*/ \ + const stm32_dma_stream_t *dmarx; \ + /* Transmit DMA stream.*/ \ + const stm32_dma_stream_t *dmatx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode + +/** + * @brief Low level fields of the SPI configuration structure. + */ +#define spi_lld_config_fields \ + /* SPI CR1 register initialization data.*/ \ + uint16_t cr1; \ + /* SPI CR2 register initialization data.*/ \ + uint16_t cr2 + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) +extern SPIDriver SPID4; +#endif + +#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) +extern SPIDriver SPID5; +#endif + +#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) +extern SPIDriver SPID6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); +#endif + void spi_lld_ignore(SPIDriver *spip, size_t n); + void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) + void spi_lld_abort(SPIDriver *spip); +#endif + uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* HAL_SPI_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv3/driver.mk b/os/hal/ports/STM32/LLD/SPIv3/driver.mk index b29942c10d..ace402b9ce 100644 --- a/os/hal/ports/STM32/LLD/SPIv3/driver.mk +++ b/os/hal/ports/STM32/LLD/SPIv3/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3 diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c index f0ef28d6da..cf1995cf84 100644 --- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c @@ -1,1142 +1,1142 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv3/hal_spi_lld.c - * @brief STM32 SPI subsystem low level driver source. - * - * @addtogroup SPI - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SPI1 driver identifier.*/ -#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) -SPIDriver SPID1; -#endif - -/** @brief SPI2 driver identifier.*/ -#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) -SPIDriver SPID2; -#endif - -/** @brief SPI3 driver identifier.*/ -#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) -SPIDriver SPID3; -#endif - -/** @brief SPI4 driver identifier.*/ -#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) -SPIDriver SPID4; -#endif - -/** @brief SPI5 driver identifier.*/ -#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) -SPIDriver SPID5; -#endif - -/** @brief SPI6 driver identifier.*/ -#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) -SPIDriver SPID6; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint32_t dummytx = STM32_SPI_FILLER_PATTERN; -static uint32_t dummyrx; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static void spi_lld_wait_complete(SPIDriver *spip) { - - while ((spip->spi->CR1 & SPI_CR1_CSTART) != 0) { - } - spip->spi->IFCR = 0xFFFFFFFF; -} - -#if defined(STM32_SPI_BDMA_REQUIRED) -/** - * @brief Shared DMA end-of-rx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_bdma_rx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & STM32_BDMA_ISR_TEIF) != 0U) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)flags; -#endif - - if (spip->config->circular) { - if ((flags & STM32_BDMA_ISR_HTIF) != 0U) { - /* Half buffer interrupt.*/ - _spi_isr_half_code(spip); - } - if ((flags & STM32_BDMA_ISR_TCIF) != 0U) { - /* End buffer interrupt.*/ - _spi_isr_full_code(spip); - } - } - else { - /* Stopping SPI.*/ - spip->spi->CR1 |= SPI_CR1_CSUSP; - - /* Stopping DMAs.*/ - bdmaStreamDisable(spip->tx.bdma); - bdmaStreamDisable(spip->rx.bdma); - - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); - } -} - -/** - * @brief Shared BDMA end-of-tx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_bdma_tx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - (void)spip; - if ((flags & STM32_BDMA_ISR_TEIF) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)spip; - (void)flags; -#endif -} -#endif /* defined(STM32_SPI_BDMA_REQUIRED) */ - -#if defined(STM32_SPI_DMA_REQUIRED) -/** - * @brief Shared DMA end-of-rx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_dma_rx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)flags; -#endif - - if (spip->config->circular) { - if ((flags & STM32_DMA_ISR_HTIF) != 0U) { - /* Half buffer interrupt.*/ - _spi_isr_half_code(spip); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0U) { - /* End buffer interrupt.*/ - _spi_isr_full_code(spip); - } - } - else { - /* Stopping SPI.*/ - spip->spi->CR1 |= SPI_CR1_CSUSP; - - /* Stopping DMAs.*/ - dmaStreamDisable(spip->tx.dma); - dmaStreamDisable(spip->rx.dma); - - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); - } -} - -/** - * @brief Shared DMA end-of-tx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_dma_tx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - (void)spip; - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)spip; - (void)flags; -#endif -} -#endif /* defined(STM32_SPI_DMA_REQUIRED) */ - -/** - * @brief Shared SPI service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - */ -static void spi_lld_serve_interrupt(SPIDriver *spip) { - uint32_t sr; - - sr = spip->spi->SR & spip->spi->IER; - spip->spi->IFCR = sr; - - if ((sr & SPI_SR_OVR) != 0U) { - /* CHTODO: fault notification.*/ - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) -#if !defined(STM32_SPI1_SUPPRESS_ISR) -#if !defined(STM32_SPI1_HANDLER) -#error "STM32_SPI1_HANDLER not defined" -#endif -/** - * @brief SPI1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SPI1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - spi_lld_serve_interrupt(&SPID1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_SPI1_SUPPRESS_ISR) */ -#endif /* STM32_SPI_USE_SPI1 */ - -#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) -#if !defined(STM32_SPI2_SUPPRESS_ISR) -#if !defined(STM32_SPI2_HANDLER) -#error "STM32_SPI2_HANDLER not defined" -#endif -/** - * @brief SPI2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SPI2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - spi_lld_serve_interrupt(&SPID2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_SPI2_SUPPRESS_ISR) */ -#endif /* STM32_SPI_USE_SPI2 */ - -#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) -#if !defined(STM32_SPI3_SUPPRESS_ISR) -#if !defined(STM32_SPI3_HANDLER) -#error "STM32_SPI3_HANDLER not defined" -#endif -/** - * @brief SPI3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SPI3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - spi_lld_serve_interrupt(&SPID3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_SPI3_SUPPRESS_ISR) */ -#endif /* STM32_SPI_USE_SPI3 */ - -#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) -#if !defined(STM32_SPI4_SUPPRESS_ISR) -#if !defined(STM32_SPI4_HANDLER) -#error "STM32_SPI4_HANDLER not defined" -#endif -/** - * @brief SPI4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SPI4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - spi_lld_serve_interrupt(&SPID4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_SPI4_SUPPRESS_ISR) */ -#endif /* STM32_SPI_USE_SPI4 */ - -#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) -#if !defined(STM32_SPI5_SUPPRESS_ISR) -#if !defined(STM32_SPI5_HANDLER) -#error "STM32_SPI5_HANDLER not defined" -#endif -/** - * @brief SPI5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SPI5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - spi_lld_serve_interrupt(&SPID5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_SPI5_SUPPRESS_ISR) */ -#endif /* STM32_SPI_USE_SPI5 */ - -#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) -#if !defined(STM32_SPI6_SUPPRESS_ISR) -#if !defined(STM32_SPI6_HANDLER) -#error "STM32_SPI6_HANDLER not defined" -#endif -/** - * @brief SPI6 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_SPI6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - spi_lld_serve_interrupt(&SPID6); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_SPI6_SUPPRESS_ISR) */ -#endif /* STM32_SPI_USE_SPI6 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SPI driver initialization. - * - * @notapi - */ -void spi_lld_init(void) { - -#if STM32_SPI_USE_SPI1 - spiObjectInit(&SPID1); - SPID1.spi = SPI1; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - SPID1.is_bdma = false; -#endif - SPID1.rx.dma = NULL; - SPID1.tx.dma = NULL; - SPID1.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID1.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#if !defined(STM32_SPI1_SUPPRESS_ISR) - nvicEnableVector(STM32_SPI1_NUMBER, STM32_SPI_SPI1_IRQ_PRIORITY); -#endif -#endif - -#if STM32_SPI_USE_SPI2 - spiObjectInit(&SPID2); - SPID2.spi = SPI2; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - SPID2.is_bdma = false; -#endif - SPID2.rx.dma = NULL; - SPID2.tx.dma = NULL; - SPID2.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID2.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#if !defined(STM32_SPI2_SUPPRESS_ISR) - nvicEnableVector(STM32_SPI2_NUMBER, STM32_SPI_SPI2_IRQ_PRIORITY); -#endif -#endif - -#if STM32_SPI_USE_SPI3 - spiObjectInit(&SPID3); - SPID3.spi = SPI3; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - SPID3.is_bdma = false; -#endif - SPID3.rx.dma = NULL; - SPID3.tx.dma = NULL; - SPID3.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID3.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#if !defined(STM32_SPI3_SUPPRESS_ISR) - nvicEnableVector(STM32_SPI3_NUMBER, STM32_SPI_SPI3_IRQ_PRIORITY); -#endif -#endif - -#if STM32_SPI_USE_SPI4 - spiObjectInit(&SPID4); - SPID4.spi = SPI4; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - SPID4.is_bdma = false; -#endif - SPID4.rx.dma = NULL; - SPID4.tx.dma = NULL; - SPID4.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID4.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#if !defined(STM32_SPI4_SUPPRESS_ISR) - nvicEnableVector(STM32_SPI4_NUMBER, STM32_SPI_SPI4_IRQ_PRIORITY); -#endif -#endif - -#if STM32_SPI_USE_SPI5 - spiObjectInit(&SPID5); - SPID5.spi = SPI5; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - SPID5.is_bdma = false; -#endif - SPID5.rx.dma = NULL; - SPID5.tx.dma = NULL; - SPID5.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID5.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#if !defined(STM32_SPI5_SUPPRESS_ISR) - nvicEnableVector(STM32_SPI5_NUMBER, STM32_SPI_SPI5_IRQ_PRIORITY); -#endif -#endif - -#if STM32_SPI_USE_SPI6 - spiObjectInit(&SPID6); - SPID6.spi = SPI6; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - SPID6.is_bdma = true; -#endif - SPID6.rx.bdma = NULL; - SPID6.tx.bdma = NULL; - SPID6.rxdmamode = STM32_BDMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | - STM32_BDMA_CR_DIR_P2M | - STM32_BDMA_CR_TCIE | - STM32_BDMA_CR_TEIE; - SPID6.txdmamode = STM32_BDMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | - STM32_BDMA_CR_DIR_M2P | - STM32_BDMA_CR_TEIE; -#if !defined(STM32_SPI6_SUPPRESS_ISR) - nvicEnableVector(STM32_SPI6_NUMBER, STM32_SPI_SPI6_IRQ_PRIORITY); -#endif -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_start(SPIDriver *spip) { - uint32_t dsize; - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (spip->state == SPI_STOP) { -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) { - spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); - spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); - rccEnableSPI1(true); - dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI1_RX); - dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI1_TX); - } -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) { - spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); - spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); - rccEnableSPI2(true); - dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI2_RX); - dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI2_TX); - } -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); - spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); - rccEnableSPI3(true); - dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI3_RX); - dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI3_TX); - } -#endif -#if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) { - spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); - spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); - rccEnableSPI4(true); - dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI4_RX); - dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI4_TX); - } -#endif -#if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) { - spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); - spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); - rccEnableSPI5(true); - dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI5_RX); - dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI5_TX); - } -#endif -#if STM32_SPI_USE_SPI6 - if (&SPID6 == spip) { - spip->rx.bdma = bdmaStreamAllocI(STM32_SPI_SPI6_RX_BDMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_bdma_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); - spip->tx.bdma = bdmaStreamAllocI(STM32_SPI_SPI6_TX_BDMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_bdma_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); - rccEnableSPI6(true); - bdmaSetRequestSource(spip->rx.bdma, STM32_DMAMUX2_SPI6_RX); - bdmaSetRequestSource(spip->tx.bdma, STM32_DMAMUX2_SPI6_TX); - } -#endif - - /* DMA setup.*/ -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamSetPeripheral(spip->rx.bdma, &spip->spi->RXDR); - bdmaStreamSetPeripheral(spip->tx.bdma, &spip->spi->TXDR); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamSetPeripheral(spip->rx.dma, &spip->spi->RXDR); - dmaStreamSetPeripheral(spip->tx.dma, &spip->spi->TXDR); - } -#endif - } - - /* Configuration-specific DMA setup.*/ - dsize = (spip->config->cfg1 & SPI_CFG1_DSIZE_Msk) + 1U; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - if (dsize <= 8U) { - /* Frame width is between 4 and 8 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) | - STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE; - spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | - STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE; - } - else if (dsize <= 16U) { - /* Frame width is between 9 and 16 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) | - STM32_BDMA_CR_PSIZE_HWORD | STM32_BDMA_CR_MSIZE_HWORD; - spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | - STM32_BDMA_CR_PSIZE_HWORD | STM32_BDMA_CR_MSIZE_HWORD; - } - else { - /* Frame width is between 16 and 32 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) | - STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD; - spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | - STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD; - } - if (spip->config->circular) { - spip->rxdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); - spip->txdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); - } - else { - spip->rxdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); - spip->txdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); - } - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - if (dsize <= 8U) { - /* Frame width is between 4 and 8 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - } - else if (dsize <= 16U) { - /* Frame width is between 9 and 16 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - else { - /* Frame width is between 16 and 32 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; - } - if (spip->config->circular) { - spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - } - else { - spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); - } - } -#endif - - /* SPI setup and enable.*/ - spip->spi->CR1 &= ~SPI_CR1_SPE; - spip->spi->CR1 = SPI_CR1_MASRX; - spip->spi->CR2 = 0U; - spip->spi->CFG1 = (spip->config->cfg1 & ~SPI_CFG1_FTHLV_Msk) | - SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN; - spip->spi->CFG2 = (spip->config->cfg2 | SPI_CFG2_MASTER | SPI_CFG2_SSOE) & - ~SPI_CFG2_COMM_Msk; - spip->spi->IER = SPI_IER_OVRIE; - spip->spi->IFCR = 0xFFFFFFFFU; - spip->spi->CR1 |= SPI_CR1_SPE; -} - -/** - * @brief Deactivates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_stop(SPIDriver *spip) { - - /* If in ready state then disables the SPI clock.*/ - if (spip->state == SPI_READY) { - - /* SPI disable.*/ - spip->spi->CR1 &= ~SPI_CR1_SPE; - spip->spi->CR1 = 0U; - spip->spi->CR2 = 0U; - spip->spi->CFG1 = 0U; - spip->spi->CFG2 = 0U; - spip->spi->IER = 0U; -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamFreeI(spip->rx.bdma); - bdmaStreamFreeI(spip->tx.bdma); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamFreeI(spip->rx.dma); - dmaStreamFreeI(spip->tx.dma); - } -#endif - -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) - rccDisableSPI1(); -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) - rccDisableSPI2(); -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) - rccDisableSPI3(); -#endif -#if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) - rccDisableSPI4(); -#endif -#if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) - rccDisableSPI5(); -#endif -#if STM32_SPI_USE_SPI6 - if (&SPID6 == spip) - rccDisableSPI6(); -#endif - } -} - -#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_select(SPIDriver *spip) { - - /* No implementation on STM32.*/ -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_unselect(SPIDriver *spip) { - - /* No implementation on STM32.*/ -} -#endif - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @notapi - */ -void spi_lld_ignore(SPIDriver *spip, size_t n) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - spi_lld_wait_complete(spip); - -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamSetMemory(spip->rx.bdma, &dummyrx); - bdmaStreamSetTransactionSize(spip->rx.bdma, n); - bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode); - - bdmaStreamSetMemory(spip->tx.bdma, &dummytx); - bdmaStreamSetTransactionSize(spip->tx.bdma, n); - bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode); - - bdmaStreamEnable(spip->rx.bdma); - bdmaStreamEnable(spip->tx.bdma); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamSetMemory0(spip->rx.dma, &dummyrx); - dmaStreamSetTransactionSize(spip->rx.dma, n); - dmaStreamSetMode(spip->rx.dma, spip->rxdmamode); - - dmaStreamSetMemory0(spip->tx.dma, &dummytx); - dmaStreamSetTransactionSize(spip->tx.dma, n); - dmaStreamSetMode(spip->tx.dma, spip->txdmamode); - - dmaStreamEnable(spip->rx.dma); - dmaStreamEnable(spip->tx.dma); - } -#endif - - spip->spi->CR1 |= SPI_CR1_CSTART; -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - spi_lld_wait_complete(spip); - -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamSetMemory(spip->rx.bdma, rxbuf); - bdmaStreamSetTransactionSize(spip->rx.bdma, n); - bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode | STM32_BDMA_CR_MINC); - - bdmaStreamSetMemory(spip->tx.bdma, txbuf); - bdmaStreamSetTransactionSize(spip->tx.bdma, n); - bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode | STM32_BDMA_CR_MINC); - - bdmaStreamEnable(spip->rx.bdma); - bdmaStreamEnable(spip->tx.bdma); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamSetMemory0(spip->rx.dma, rxbuf); - dmaStreamSetTransactionSize(spip->rx.dma, n); - dmaStreamSetMode(spip->rx.dma, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->tx.dma, txbuf); - dmaStreamSetTransactionSize(spip->tx.dma, n); - dmaStreamSetMode(spip->tx.dma, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->rx.dma); - dmaStreamEnable(spip->tx.dma); - } -#endif - - spip->spi->CR1 |= SPI_CR1_CSTART; -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - spi_lld_wait_complete(spip); - -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamSetMemory(spip->rx.bdma, &dummyrx); - bdmaStreamSetTransactionSize(spip->rx.bdma, n); - bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode); - - bdmaStreamSetMemory(spip->tx.bdma, txbuf); - bdmaStreamSetTransactionSize(spip->tx.bdma, n); - bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode | STM32_BDMA_CR_MINC); - - bdmaStreamEnable(spip->rx.bdma); - bdmaStreamEnable(spip->tx.bdma); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamSetMemory0(spip->rx.dma, &dummyrx); - dmaStreamSetTransactionSize(spip->rx.dma, n); - dmaStreamSetMode(spip->rx.dma, spip->rxdmamode); - - dmaStreamSetMemory0(spip->tx.dma, txbuf); - dmaStreamSetTransactionSize(spip->tx.dma, n); - dmaStreamSetMode(spip->tx.dma, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->rx.dma); - dmaStreamEnable(spip->tx.dma); - } -#endif - - spip->spi->CR1 |= SPI_CR1_CSTART; -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { - - osalDbgAssert(n < 65536, "unsupported DMA transfer size"); - - spi_lld_wait_complete(spip); - -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamSetMemory(spip->rx.bdma, rxbuf); - bdmaStreamSetTransactionSize(spip->rx.bdma, n); - bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode | STM32_BDMA_CR_MINC); - - bdmaStreamSetMemory(spip->tx.bdma, &dummytx); - bdmaStreamSetTransactionSize(spip->tx.bdma, n); - bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode); - - bdmaStreamEnable(spip->rx.bdma); - bdmaStreamEnable(spip->tx.bdma); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamSetMemory0(spip->rx.dma, rxbuf); - dmaStreamSetTransactionSize(spip->rx.dma, n); - dmaStreamSetMode(spip->rx.dma, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->tx.dma, &dummytx); - dmaStreamSetTransactionSize(spip->tx.dma, n); - dmaStreamSetMode(spip->tx.dma, spip->txdmamode); - - dmaStreamEnable(spip->rx.dma); - dmaStreamEnable(spip->tx.dma); - } -#endif - - spip->spi->CR1 |= SPI_CR1_CSTART; -} - -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) -/** - * @brief Aborts the ongoing SPI operation, if any. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_abort(SPIDriver *spip) { - - /* Stopping SPI.*/ - spip->spi->CR1 |= SPI_CR1_CSUSP; - - spi_lld_wait_complete(spip); - - /* Stopping DMAs.*/ -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - if (spip->is_bdma) -#endif -#if defined(STM32_SPI_BDMA_REQUIRED) - { - bdmaStreamDisable(spip->tx.bdma); - bdmaStreamDisable(spip->rx.bdma); - } -#endif -#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) - else -#endif -#if defined(STM32_SPI_DMA_REQUIRED) - { - dmaStreamDisable(spip->tx.dma); - dmaStreamDisable(spip->rx.dma); - } -#endif -} -#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ - -/** - * @brief Exchanges one frame using a polled wait. - * @details This synchronous function exchanges one frame using a polled - * synchronization method. This function is useful when exchanging - * small amount of data on high speed channels, usually in this - * situation is much more efficient just wait for completion using - * polling than suspending the thread waiting for an interrupt. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] frame the data frame to send over the SPI bus - * @return The received data frame from the SPI bus. - * - * @notapi - */ -uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame) { - uint32_t dsize = (spip->spi->CFG1 & SPI_CFG1_DSIZE_Msk) + 1U; - uint32_t rxframe; - - spi_lld_wait_complete(spip); - - spip->spi->CR1 |= SPI_CR1_CSTART; - - /* wait for room in TX FIFO.*/ - while ((spip->spi->SR & SPI_SR_TXP) == 0U) - ; - - /* Data register must be accessed with the appropriate data size. - Byte size access (uint8_t *) for transactions that are <= 8-bit etc.*/ - if (dsize <= 8U) { - /* Frame width is between 4 and 8 bits.*/ - volatile uint8_t *txdrp8 = (volatile uint8_t *)&spip->spi->TXDR; - volatile uint8_t *rxdrp8 = (volatile uint8_t *)&spip->spi->RXDR; - *txdrp8 = (uint8_t)frame; - while ((spip->spi->SR & SPI_SR_RXP) == 0U) - ; - rxframe = (uint32_t)*rxdrp8; - } - else if (dsize <= 16U) { - /* Frame width is between 9 and 16 bits.*/ - volatile uint16_t *txdrp16 = (volatile uint16_t *)&spip->spi->TXDR; - volatile uint16_t *rxdrp16 = (volatile uint16_t *)&spip->spi->RXDR; - *txdrp16 = (uint16_t)frame; - while ((spip->spi->SR & SPI_SR_RXP) == 0U) - ; - rxframe = (uint32_t)*rxdrp16; - } - else { - /* Frame width is between 16 and 32 bits.*/ - spip->spi->TXDR = frame; - while ((spip->spi->SR & SPI_SR_RXP) == 0U) - ; - rxframe = spip->spi->RXDR; - } - - spip->spi->CR1 |= SPI_CR1_CSUSP; - - return rxframe; -} - -#endif /* HAL_USE_SPI */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv3/hal_spi_lld.c + * @brief STM32 SPI subsystem low level driver source. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SPI1 driver identifier.*/ +#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/** @brief SPI2 driver identifier.*/ +#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/** @brief SPI3 driver identifier.*/ +#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) +SPIDriver SPID3; +#endif + +/** @brief SPI4 driver identifier.*/ +#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) +SPIDriver SPID4; +#endif + +/** @brief SPI5 driver identifier.*/ +#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) +SPIDriver SPID5; +#endif + +/** @brief SPI6 driver identifier.*/ +#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) +SPIDriver SPID6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint32_t dummytx = STM32_SPI_FILLER_PATTERN; +static uint32_t dummyrx; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void spi_lld_wait_complete(SPIDriver *spip) { + + while ((spip->spi->CR1 & SPI_CR1_CSTART) != 0) { + } + spip->spi->IFCR = 0xFFFFFFFF; +} + +#if defined(STM32_SPI_BDMA_REQUIRED) +/** + * @brief Shared DMA end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_bdma_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & STM32_BDMA_ISR_TEIF) != 0U) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif + + if (spip->config->circular) { + if ((flags & STM32_BDMA_ISR_HTIF) != 0U) { + /* Half buffer interrupt.*/ + _spi_isr_half_code(spip); + } + if ((flags & STM32_BDMA_ISR_TCIF) != 0U) { + /* End buffer interrupt.*/ + _spi_isr_full_code(spip); + } + } + else { + /* Stopping SPI.*/ + spip->spi->CR1 |= SPI_CR1_CSUSP; + + /* Stopping DMAs.*/ + bdmaStreamDisable(spip->tx.bdma); + bdmaStreamDisable(spip->rx.bdma); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); + } +} + +/** + * @brief Shared BDMA end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_bdma_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & STM32_BDMA_ISR_TEIF) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} +#endif /* defined(STM32_SPI_BDMA_REQUIRED) */ + +#if defined(STM32_SPI_DMA_REQUIRED) +/** + * @brief Shared DMA end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_dma_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif + + if (spip->config->circular) { + if ((flags & STM32_DMA_ISR_HTIF) != 0U) { + /* Half buffer interrupt.*/ + _spi_isr_half_code(spip); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0U) { + /* End buffer interrupt.*/ + _spi_isr_full_code(spip); + } + } + else { + /* Stopping SPI.*/ + spip->spi->CR1 |= SPI_CR1_CSUSP; + + /* Stopping DMAs.*/ + dmaStreamDisable(spip->tx.dma); + dmaStreamDisable(spip->rx.dma); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); + } +} + +/** + * @brief Shared DMA end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_dma_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} +#endif /* defined(STM32_SPI_DMA_REQUIRED) */ + +/** + * @brief Shared SPI service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +static void spi_lld_serve_interrupt(SPIDriver *spip) { + uint32_t sr; + + sr = spip->spi->SR & spip->spi->IER; + spip->spi->IFCR = sr; + + if ((sr & SPI_SR_OVR) != 0U) { + /* CHTODO: fault notification.*/ + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) +#if !defined(STM32_SPI1_SUPPRESS_ISR) +#if !defined(STM32_SPI1_HANDLER) +#error "STM32_SPI1_HANDLER not defined" +#endif +/** + * @brief SPI1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SPI1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + spi_lld_serve_interrupt(&SPID1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_SPI1_SUPPRESS_ISR) */ +#endif /* STM32_SPI_USE_SPI1 */ + +#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) +#if !defined(STM32_SPI2_SUPPRESS_ISR) +#if !defined(STM32_SPI2_HANDLER) +#error "STM32_SPI2_HANDLER not defined" +#endif +/** + * @brief SPI2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SPI2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + spi_lld_serve_interrupt(&SPID2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_SPI2_SUPPRESS_ISR) */ +#endif /* STM32_SPI_USE_SPI2 */ + +#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) +#if !defined(STM32_SPI3_SUPPRESS_ISR) +#if !defined(STM32_SPI3_HANDLER) +#error "STM32_SPI3_HANDLER not defined" +#endif +/** + * @brief SPI3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SPI3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + spi_lld_serve_interrupt(&SPID3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_SPI3_SUPPRESS_ISR) */ +#endif /* STM32_SPI_USE_SPI3 */ + +#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__) +#if !defined(STM32_SPI4_SUPPRESS_ISR) +#if !defined(STM32_SPI4_HANDLER) +#error "STM32_SPI4_HANDLER not defined" +#endif +/** + * @brief SPI4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SPI4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + spi_lld_serve_interrupt(&SPID4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_SPI4_SUPPRESS_ISR) */ +#endif /* STM32_SPI_USE_SPI4 */ + +#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__) +#if !defined(STM32_SPI5_SUPPRESS_ISR) +#if !defined(STM32_SPI5_HANDLER) +#error "STM32_SPI5_HANDLER not defined" +#endif +/** + * @brief SPI5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SPI5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + spi_lld_serve_interrupt(&SPID5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_SPI5_SUPPRESS_ISR) */ +#endif /* STM32_SPI_USE_SPI5 */ + +#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__) +#if !defined(STM32_SPI6_SUPPRESS_ISR) +#if !defined(STM32_SPI6_HANDLER) +#error "STM32_SPI6_HANDLER not defined" +#endif +/** + * @brief SPI6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_SPI6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + spi_lld_serve_interrupt(&SPID6); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_SPI6_SUPPRESS_ISR) */ +#endif /* STM32_SPI_USE_SPI6 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { + +#if STM32_SPI_USE_SPI1 + spiObjectInit(&SPID1); + SPID1.spi = SPI1; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + SPID1.is_bdma = false; +#endif + SPID1.rx.dma = NULL; + SPID1.tx.dma = NULL; + SPID1.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID1.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#if !defined(STM32_SPI1_SUPPRESS_ISR) + nvicEnableVector(STM32_SPI1_NUMBER, STM32_SPI_SPI1_IRQ_PRIORITY); +#endif +#endif + +#if STM32_SPI_USE_SPI2 + spiObjectInit(&SPID2); + SPID2.spi = SPI2; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + SPID2.is_bdma = false; +#endif + SPID2.rx.dma = NULL; + SPID2.tx.dma = NULL; + SPID2.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID2.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#if !defined(STM32_SPI2_SUPPRESS_ISR) + nvicEnableVector(STM32_SPI2_NUMBER, STM32_SPI_SPI2_IRQ_PRIORITY); +#endif +#endif + +#if STM32_SPI_USE_SPI3 + spiObjectInit(&SPID3); + SPID3.spi = SPI3; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + SPID3.is_bdma = false; +#endif + SPID3.rx.dma = NULL; + SPID3.tx.dma = NULL; + SPID3.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID3.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#if !defined(STM32_SPI3_SUPPRESS_ISR) + nvicEnableVector(STM32_SPI3_NUMBER, STM32_SPI_SPI3_IRQ_PRIORITY); +#endif +#endif + +#if STM32_SPI_USE_SPI4 + spiObjectInit(&SPID4); + SPID4.spi = SPI4; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + SPID4.is_bdma = false; +#endif + SPID4.rx.dma = NULL; + SPID4.tx.dma = NULL; + SPID4.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID4.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#if !defined(STM32_SPI4_SUPPRESS_ISR) + nvicEnableVector(STM32_SPI4_NUMBER, STM32_SPI_SPI4_IRQ_PRIORITY); +#endif +#endif + +#if STM32_SPI_USE_SPI5 + spiObjectInit(&SPID5); + SPID5.spi = SPI5; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + SPID5.is_bdma = false; +#endif + SPID5.rx.dma = NULL; + SPID5.tx.dma = NULL; + SPID5.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID5.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#if !defined(STM32_SPI5_SUPPRESS_ISR) + nvicEnableVector(STM32_SPI5_NUMBER, STM32_SPI_SPI5_IRQ_PRIORITY); +#endif +#endif + +#if STM32_SPI_USE_SPI6 + spiObjectInit(&SPID6); + SPID6.spi = SPI6; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + SPID6.is_bdma = true; +#endif + SPID6.rx.bdma = NULL; + SPID6.tx.bdma = NULL; + SPID6.rxdmamode = STM32_BDMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | + STM32_BDMA_CR_DIR_P2M | + STM32_BDMA_CR_TCIE | + STM32_BDMA_CR_TEIE; + SPID6.txdmamode = STM32_BDMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) | + STM32_BDMA_CR_DIR_M2P | + STM32_BDMA_CR_TEIE; +#if !defined(STM32_SPI6_SUPPRESS_ISR) + nvicEnableVector(STM32_SPI6_NUMBER, STM32_SPI_SPI6_IRQ_PRIORITY); +#endif +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_start(SPIDriver *spip) { + uint32_t dsize; + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (spip->state == SPI_STOP) { +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) { + spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); + spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); + rccEnableSPI1(true); + dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI1_RX); + dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI1_TX); + } +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) { + spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); + spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); + rccEnableSPI2(true); + dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI2_RX); + dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI2_TX); + } +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) { + spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); + spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); + rccEnableSPI3(true); + dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI3_RX); + dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI3_TX); + } +#endif +#if STM32_SPI_USE_SPI4 + if (&SPID4 == spip) { + spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); + spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); + rccEnableSPI4(true); + dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI4_RX); + dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI4_TX); + } +#endif +#if STM32_SPI_USE_SPI5 + if (&SPID5 == spip) { + spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); + spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); + rccEnableSPI5(true); + dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI5_RX); + dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI5_TX); + } +#endif +#if STM32_SPI_USE_SPI6 + if (&SPID6 == spip) { + spip->rx.bdma = bdmaStreamAllocI(STM32_SPI_SPI6_RX_BDMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_bdma_rx_interrupt, + (void *)spip); + osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream"); + spip->tx.bdma = bdmaStreamAllocI(STM32_SPI_SPI6_TX_BDMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_bdma_tx_interrupt, + (void *)spip); + osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream"); + rccEnableSPI6(true); + bdmaSetRequestSource(spip->rx.bdma, STM32_DMAMUX2_SPI6_RX); + bdmaSetRequestSource(spip->tx.bdma, STM32_DMAMUX2_SPI6_TX); + } +#endif + + /* DMA setup.*/ +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamSetPeripheral(spip->rx.bdma, &spip->spi->RXDR); + bdmaStreamSetPeripheral(spip->tx.bdma, &spip->spi->TXDR); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamSetPeripheral(spip->rx.dma, &spip->spi->RXDR); + dmaStreamSetPeripheral(spip->tx.dma, &spip->spi->TXDR); + } +#endif + } + + /* Configuration-specific DMA setup.*/ + dsize = (spip->config->cfg1 & SPI_CFG1_DSIZE_Msk) + 1U; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + if (dsize <= 8U) { + /* Frame width is between 4 and 8 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) | + STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE; + spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | + STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE; + } + else if (dsize <= 16U) { + /* Frame width is between 9 and 16 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) | + STM32_BDMA_CR_PSIZE_HWORD | STM32_BDMA_CR_MSIZE_HWORD; + spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | + STM32_BDMA_CR_PSIZE_HWORD | STM32_BDMA_CR_MSIZE_HWORD; + } + else { + /* Frame width is between 16 and 32 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) | + STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD; + spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | + STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD; + } + if (spip->config->circular) { + spip->rxdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + spip->txdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + } + else { + spip->rxdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + spip->txdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + } + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + if (dsize <= 8U) { + /* Frame width is between 4 and 8 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + } + else if (dsize <= 16U) { + /* Frame width is between 9 and 16 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + else { + /* Frame width is between 16 and 32 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; + } + if (spip->config->circular) { + spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + else { + spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + } +#endif + + /* SPI setup and enable.*/ + spip->spi->CR1 &= ~SPI_CR1_SPE; + spip->spi->CR1 = SPI_CR1_MASRX; + spip->spi->CR2 = 0U; + spip->spi->CFG1 = (spip->config->cfg1 & ~SPI_CFG1_FTHLV_Msk) | + SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN; + spip->spi->CFG2 = (spip->config->cfg2 | SPI_CFG2_MASTER | SPI_CFG2_SSOE) & + ~SPI_CFG2_COMM_Msk; + spip->spi->IER = SPI_IER_OVRIE; + spip->spi->IFCR = 0xFFFFFFFFU; + spip->spi->CR1 |= SPI_CR1_SPE; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->state == SPI_READY) { + + /* SPI disable.*/ + spip->spi->CR1 &= ~SPI_CR1_SPE; + spip->spi->CR1 = 0U; + spip->spi->CR2 = 0U; + spip->spi->CFG1 = 0U; + spip->spi->CFG2 = 0U; + spip->spi->IER = 0U; +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamFreeI(spip->rx.bdma); + bdmaStreamFreeI(spip->tx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamFreeI(spip->rx.dma); + dmaStreamFreeI(spip->tx.dma); + } +#endif + +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) + rccDisableSPI1(); +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) + rccDisableSPI2(); +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) + rccDisableSPI3(); +#endif +#if STM32_SPI_USE_SPI4 + if (&SPID4 == spip) + rccDisableSPI4(); +#endif +#if STM32_SPI_USE_SPI5 + if (&SPID5 == spip) + rccDisableSPI5(); +#endif +#if STM32_SPI_USE_SPI6 + if (&SPID6 == spip) + rccDisableSPI6(); +#endif + } +} + +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + /* No implementation on STM32.*/ +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + /* No implementation on STM32.*/ +} +#endif + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @notapi + */ +void spi_lld_ignore(SPIDriver *spip, size_t n) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + spi_lld_wait_complete(spip); + +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamSetMemory(spip->rx.bdma, &dummyrx); + bdmaStreamSetTransactionSize(spip->rx.bdma, n); + bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode); + + bdmaStreamSetMemory(spip->tx.bdma, &dummytx); + bdmaStreamSetTransactionSize(spip->tx.bdma, n); + bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode); + + bdmaStreamEnable(spip->rx.bdma); + bdmaStreamEnable(spip->tx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamSetMemory0(spip->rx.dma, &dummyrx); + dmaStreamSetTransactionSize(spip->rx.dma, n); + dmaStreamSetMode(spip->rx.dma, spip->rxdmamode); + + dmaStreamSetMemory0(spip->tx.dma, &dummytx); + dmaStreamSetTransactionSize(spip->tx.dma, n); + dmaStreamSetMode(spip->tx.dma, spip->txdmamode); + + dmaStreamEnable(spip->rx.dma); + dmaStreamEnable(spip->tx.dma); + } +#endif + + spip->spi->CR1 |= SPI_CR1_CSTART; +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + spi_lld_wait_complete(spip); + +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamSetMemory(spip->rx.bdma, rxbuf); + bdmaStreamSetTransactionSize(spip->rx.bdma, n); + bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode | STM32_BDMA_CR_MINC); + + bdmaStreamSetMemory(spip->tx.bdma, txbuf); + bdmaStreamSetTransactionSize(spip->tx.bdma, n); + bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode | STM32_BDMA_CR_MINC); + + bdmaStreamEnable(spip->rx.bdma); + bdmaStreamEnable(spip->tx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamSetMemory0(spip->rx.dma, rxbuf); + dmaStreamSetTransactionSize(spip->rx.dma, n); + dmaStreamSetMode(spip->rx.dma, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->tx.dma, txbuf); + dmaStreamSetTransactionSize(spip->tx.dma, n); + dmaStreamSetMode(spip->tx.dma, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->rx.dma); + dmaStreamEnable(spip->tx.dma); + } +#endif + + spip->spi->CR1 |= SPI_CR1_CSTART; +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + spi_lld_wait_complete(spip); + +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamSetMemory(spip->rx.bdma, &dummyrx); + bdmaStreamSetTransactionSize(spip->rx.bdma, n); + bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode); + + bdmaStreamSetMemory(spip->tx.bdma, txbuf); + bdmaStreamSetTransactionSize(spip->tx.bdma, n); + bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode | STM32_BDMA_CR_MINC); + + bdmaStreamEnable(spip->rx.bdma); + bdmaStreamEnable(spip->tx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamSetMemory0(spip->rx.dma, &dummyrx); + dmaStreamSetTransactionSize(spip->rx.dma, n); + dmaStreamSetMode(spip->rx.dma, spip->rxdmamode); + + dmaStreamSetMemory0(spip->tx.dma, txbuf); + dmaStreamSetTransactionSize(spip->tx.dma, n); + dmaStreamSetMode(spip->tx.dma, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->rx.dma); + dmaStreamEnable(spip->tx.dma); + } +#endif + + spip->spi->CR1 |= SPI_CR1_CSTART; +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgAssert(n < 65536, "unsupported DMA transfer size"); + + spi_lld_wait_complete(spip); + +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamSetMemory(spip->rx.bdma, rxbuf); + bdmaStreamSetTransactionSize(spip->rx.bdma, n); + bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode | STM32_BDMA_CR_MINC); + + bdmaStreamSetMemory(spip->tx.bdma, &dummytx); + bdmaStreamSetTransactionSize(spip->tx.bdma, n); + bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode); + + bdmaStreamEnable(spip->rx.bdma); + bdmaStreamEnable(spip->tx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamSetMemory0(spip->rx.dma, rxbuf); + dmaStreamSetTransactionSize(spip->rx.dma, n); + dmaStreamSetMode(spip->rx.dma, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->tx.dma, &dummytx); + dmaStreamSetTransactionSize(spip->tx.dma, n); + dmaStreamSetMode(spip->tx.dma, spip->txdmamode); + + dmaStreamEnable(spip->rx.dma); + dmaStreamEnable(spip->tx.dma); + } +#endif + + spip->spi->CR1 |= SPI_CR1_CSTART; +} + +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) +/** + * @brief Aborts the ongoing SPI operation, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_abort(SPIDriver *spip) { + + /* Stopping SPI.*/ + spip->spi->CR1 |= SPI_CR1_CSUSP; + + spi_lld_wait_complete(spip); + + /* Stopping DMAs.*/ +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if (spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamDisable(spip->tx.bdma); + bdmaStreamDisable(spip->rx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamDisable(spip->tx.dma); + dmaStreamDisable(spip->rx.dma); + } +#endif +} +#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + * + * @notapi + */ +uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame) { + uint32_t dsize = (spip->spi->CFG1 & SPI_CFG1_DSIZE_Msk) + 1U; + uint32_t rxframe; + + spi_lld_wait_complete(spip); + + spip->spi->CR1 |= SPI_CR1_CSTART; + + /* wait for room in TX FIFO.*/ + while ((spip->spi->SR & SPI_SR_TXP) == 0U) + ; + + /* Data register must be accessed with the appropriate data size. + Byte size access (uint8_t *) for transactions that are <= 8-bit etc.*/ + if (dsize <= 8U) { + /* Frame width is between 4 and 8 bits.*/ + volatile uint8_t *txdrp8 = (volatile uint8_t *)&spip->spi->TXDR; + volatile uint8_t *rxdrp8 = (volatile uint8_t *)&spip->spi->RXDR; + *txdrp8 = (uint8_t)frame; + while ((spip->spi->SR & SPI_SR_RXP) == 0U) + ; + rxframe = (uint32_t)*rxdrp8; + } + else if (dsize <= 16U) { + /* Frame width is between 9 and 16 bits.*/ + volatile uint16_t *txdrp16 = (volatile uint16_t *)&spip->spi->TXDR; + volatile uint16_t *rxdrp16 = (volatile uint16_t *)&spip->spi->RXDR; + *txdrp16 = (uint16_t)frame; + while ((spip->spi->SR & SPI_SR_RXP) == 0U) + ; + rxframe = (uint32_t)*rxdrp16; + } + else { + /* Frame width is between 16 and 32 bits.*/ + spip->spi->TXDR = frame; + while ((spip->spi->SR & SPI_SR_RXP) == 0U) + ; + rxframe = spip->spi->RXDR; + } + + spip->spi->CR1 |= SPI_CR1_CSUSP; + + return rxframe; +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h index 133fedf4dc..13b420327f 100644 --- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h +++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h @@ -1,590 +1,590 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file SPIv3/hal_spi_lld.h - * @brief STM32 SPI subsystem low level driver header. - * - * @addtogroup SPI - * @{ - */ - -#ifndef HAL_SPI_LLD_H -#define HAL_SPI_LLD_H - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Circular mode support flag. - */ -#define SPI_SUPPORTS_CIRCULAR TRUE - -/** - * @name Register helpers not found in ST headers - * @{ - */ -#define SPI_CFG1_MBR_VALUE(n) ((n) << SPI_CFG1_MBR_Pos) -#define SPI_CFG1_MBR_DIV2 SPI_CFG1_MBR_VALUE(0) -#define SPI_CFG1_MBR_DIV4 SPI_CFG1_MBR_VALUE(1) -#define SPI_CFG1_MBR_DIV8 SPI_CFG1_MBR_VALUE(2) -#define SPI_CFG1_MBR_DIV16 SPI_CFG1_MBR_VALUE(3) -#define SPI_CFG1_MBR_DIV32 SPI_CFG1_MBR_VALUE(4) -#define SPI_CFG1_MBR_DIV64 SPI_CFG1_MBR_VALUE(5) -#define SPI_CFG1_MBR_DIV128 SPI_CFG1_MBR_VALUE(6) -#define SPI_CFG1_MBR_DIV256 SPI_CFG1_MBR_VALUE(7) -#define SPI_CFG1_CRCSIZE_VALUE(n) ((n) << SPI_CFG1_CRCSIZE_Pos) -#define SPI_CFG1_UDRDET_VALUE(n) ((n) << SPI_CFG1_UDRDET_Pos) -#define SPI_CFG1_UDRCFG_VALUE(n) ((n) << SPI_CFG1_UDRCFG_Pos) -#define SPI_CFG1_FTHLV_VALUE(n) ((n) << SPI_CFG1_FTHLV_Pos) -#define SPI_CFG1_DSIZE_VALUE(n) ((n) << SPI_CFG1_DSIZE_Pos) - -#define SPI_CFG2_SP_VALUE(n) ((n) << SPI_CFG2_SP_Pos) -#define SPI_CFG2_COMM_VALUE(n) ((n) << SPI_CFG2_COMM_Pos) -#define SPI_CFG2_COMM_FULL_DUPLEX SPI_CFG2_COMM_VALUE(0) -#define SPI_CFG2_COMM_TRANSMITTER SPI_CFG2_COMM_VALUE(1) -#define SPI_CFG2_COMM_RECEIVER SPI_CFG2_COMM_VALUE(2) -#define SPI_CFG2_COMM_HALF_DUPLEX SPI_CFG2_COMM_VALUE(3) -#define SPI_CFG2_MIDI_VALUE(n) ((n) << SPI_CFG2_MIDI_Pos) -#define SPI_CFG2_MSSI_VALUE(n) ((n) << SPI_CFG2_MSSI_Pos) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SPI1 driver enable switch. - * @details If set to @p TRUE the support for SPI1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI1 FALSE -#endif - -/** - * @brief SPI2 driver enable switch. - * @details If set to @p TRUE the support for SPI2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI2 FALSE -#endif - -/** - * @brief SPI3 driver enable switch. - * @details If set to @p TRUE the support for SPI3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI3 FALSE -#endif - -/** - * @brief SPI4 driver enable switch. - * @details If set to @p TRUE the support for SPI4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI4 FALSE -#endif - -/** - * @brief SPI5 driver enable switch. - * @details If set to @p TRUE the support for SPI5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI5 FALSE -#endif - -/** - * @brief SPI6 driver enable switch. - * @details If set to @p TRUE the support for SPI6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI6 FALSE -#endif - -/** - * @brief Filler pattern used when there is nothing to transmit. - */ -#if !defined(STM32_SPI_FILLER_PATTERN) || defined(__DOXYGEN__) -#define STM32_SPI_FILLER_PATTERN 0xFFFFFFFFU -#endif - -/** - * @brief SPI1 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI2 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI3 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI4 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI4_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI5 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI5_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI6 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI6_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI4_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI5 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI5_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI6 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI6_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI DMA error hook. - */ -#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 -#error "SPI4 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 -#error "SPI5 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 -#error "SPI6 not present in the selected device" -#endif - -#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ - !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 -#error "SPI driver activated but no SPI peripheral assigned" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI4" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI5" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI6" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) -#error "SPI1 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) -#error "SPI2 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) -#error "SPI3 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) -#error "SPI4 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) -#error "SPI5 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_BDMA_STREAM) || \ - !defined(STM32_SPI_SPI6_TX_BDMA_STREAM)) -#error "SPI6 BDMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA streams.*/ -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI1 RX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI1 TX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI2 RX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI2 TX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI3 RX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI3 TX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI4 RX" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI4 TX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI5 RX" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM) -#error "Invalid DMA stream assigned to SPI5 TX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_BDMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_BDMA_STREAM) -#error "Invalid BDMA stream assigned to SPI6 RX" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_BDMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_BDMA_STREAM) -#error "Invalid BDMA stream assigned to SPI6 TX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI4" -#endif - -#if STM32_SPI_USE_SPI5 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI5" -#endif - -#if STM32_SPI_USE_SPI6 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI6" -#endif - -#if STM32_SPI_USE_SPI1 || STM32_SPI_USE_SPI2 || STM32_SPI_USE_SPI3 || \ - STM32_SPI_USE_SPI4 || STM32_SPI_USE_SPI5 -#define STM32_SPI_DMA_REQUIRED -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif -#endif - -#if STM32_SPI_USE_SPI6 -#define STM32_SPI_BDMA_REQUIRED -#if !defined(STM32_BDMA_REQUIRED) -#define STM32_BDMA_REQUIRED -#endif -#endif - -#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD -#error "SPI_SELECT_MODE_LLD not supported by this driver" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -#if (defined(STM32_SPI_DMA_REQUIRED) && \ - defined(STM32_SPI_BDMA_REQUIRED)) || defined(__DOXYGEN__) -#define spi_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /** DMA type for this instance.*/ \ - bool is_bdma; \ - /** Union of the RX DMA streams.*/ \ - union { \ - /* Receive DMA stream.*/ \ - const stm32_dma_stream_t *dma; \ - /* Receive BDMA stream.*/ \ - const stm32_bdma_stream_t *bdma; \ - } rx; \ - /* Union of the TX DMA streams.*/ \ - union { \ - /* Transmit DMA stream.*/ \ - const stm32_dma_stream_t *dma; \ - /* Transmit DMA stream.*/ \ - const stm32_bdma_stream_t *bdma; \ - } tx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode -#endif - -#if defined(STM32_SPI_DMA_REQUIRED) && !defined(STM32_SPI_BDMA_REQUIRED) -#define spi_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /** Union of the RX DMA streams.*/ \ - union { \ - /* Receive DMA stream.*/ \ - const stm32_dma_stream_t *dma; \ - } rx; \ - /* Union of the TX DMA streams.*/ \ - union { \ - /* Transmit DMA stream.*/ \ - const stm32_dma_stream_t *dma; \ - } tx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode -#endif - -#if !defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) -#define spi_lld_driver_fields \ - /* Pointer to the SPIx registers block.*/ \ - SPI_TypeDef *spi; \ - /** Union of the RX DMA streams.*/ \ - union { \ - /* Receive BDMA stream.*/ \ - const stm32_bdma_stream_t *bdma; \ - } rx; \ - /* Union of the TX DMA streams.*/ \ - union { \ - /* Transmit DMA stream.*/ \ - const stm32_bdma_stream_t *bdma; \ - } tx; \ - /* RX DMA mode bit mask.*/ \ - uint32_t rxdmamode; \ - /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode -#endif - -/** - * @brief Low level fields of the SPI configuration structure. - */ -#define spi_lld_config_fields \ - /* SPI CFG1 register initialization data.*/ \ - uint32_t cfg1; \ - /* SPI CFG2 register initialization data.*/ \ - uint32_t cfg2 - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) -extern SPIDriver SPID1; -#endif - -#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) -extern SPIDriver SPID2; -#endif - -#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) -extern SPIDriver SPID3; -#endif - -#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) -extern SPIDriver SPID4; -#endif - -#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) -extern SPIDriver SPID5; -#endif - -#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) -extern SPIDriver SPID6; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void spi_lld_init(void); - void spi_lld_start(SPIDriver *spip); - void spi_lld_stop(SPIDriver *spip); -#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) - void spi_lld_select(SPIDriver *spip); - void spi_lld_unselect(SPIDriver *spip); -#endif - void spi_lld_ignore(SPIDriver *spip, size_t n); - void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); - void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) - void spi_lld_abort(SPIDriver *spip); -#endif - uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SPI */ - -#endif /* HAL_SPI_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv3/hal_spi_lld.h + * @brief STM32 SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef HAL_SPI_LLD_H +#define HAL_SPI_LLD_H + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Circular mode support flag. + */ +#define SPI_SUPPORTS_CIRCULAR TRUE + +/** + * @name Register helpers not found in ST headers + * @{ + */ +#define SPI_CFG1_MBR_VALUE(n) ((n) << SPI_CFG1_MBR_Pos) +#define SPI_CFG1_MBR_DIV2 SPI_CFG1_MBR_VALUE(0) +#define SPI_CFG1_MBR_DIV4 SPI_CFG1_MBR_VALUE(1) +#define SPI_CFG1_MBR_DIV8 SPI_CFG1_MBR_VALUE(2) +#define SPI_CFG1_MBR_DIV16 SPI_CFG1_MBR_VALUE(3) +#define SPI_CFG1_MBR_DIV32 SPI_CFG1_MBR_VALUE(4) +#define SPI_CFG1_MBR_DIV64 SPI_CFG1_MBR_VALUE(5) +#define SPI_CFG1_MBR_DIV128 SPI_CFG1_MBR_VALUE(6) +#define SPI_CFG1_MBR_DIV256 SPI_CFG1_MBR_VALUE(7) +#define SPI_CFG1_CRCSIZE_VALUE(n) ((n) << SPI_CFG1_CRCSIZE_Pos) +#define SPI_CFG1_UDRDET_VALUE(n) ((n) << SPI_CFG1_UDRDET_Pos) +#define SPI_CFG1_UDRCFG_VALUE(n) ((n) << SPI_CFG1_UDRCFG_Pos) +#define SPI_CFG1_FTHLV_VALUE(n) ((n) << SPI_CFG1_FTHLV_Pos) +#define SPI_CFG1_DSIZE_VALUE(n) ((n) << SPI_CFG1_DSIZE_Pos) + +#define SPI_CFG2_SP_VALUE(n) ((n) << SPI_CFG2_SP_Pos) +#define SPI_CFG2_COMM_VALUE(n) ((n) << SPI_CFG2_COMM_Pos) +#define SPI_CFG2_COMM_FULL_DUPLEX SPI_CFG2_COMM_VALUE(0) +#define SPI_CFG2_COMM_TRANSMITTER SPI_CFG2_COMM_VALUE(1) +#define SPI_CFG2_COMM_RECEIVER SPI_CFG2_COMM_VALUE(2) +#define SPI_CFG2_COMM_HALF_DUPLEX SPI_CFG2_COMM_VALUE(3) +#define SPI_CFG2_MIDI_VALUE(n) ((n) << SPI_CFG2_MIDI_Pos) +#define SPI_CFG2_MSSI_VALUE(n) ((n) << SPI_CFG2_MSSI_Pos) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI2 driver enable switch. + * @details If set to @p TRUE the support for SPI2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI2 FALSE +#endif + +/** + * @brief SPI3 driver enable switch. + * @details If set to @p TRUE the support for SPI3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI3 FALSE +#endif + +/** + * @brief SPI4 driver enable switch. + * @details If set to @p TRUE the support for SPI4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI4 FALSE +#endif + +/** + * @brief SPI5 driver enable switch. + * @details If set to @p TRUE the support for SPI5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI5 FALSE +#endif + +/** + * @brief SPI6 driver enable switch. + * @details If set to @p TRUE the support for SPI6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI6 FALSE +#endif + +/** + * @brief Filler pattern used when there is nothing to transmit. + */ +#if !defined(STM32_SPI_FILLER_PATTERN) || defined(__DOXYGEN__) +#define STM32_SPI_FILLER_PATTERN 0xFFFFFFFFU +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI2 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI3 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI4 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI5 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI6 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI DMA error hook. + */ +#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 +#error "SPI4 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 +#error "SPI5 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 +#error "SPI6 not present in the selected device" +#endif + +#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ + !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI6" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) +#error "SPI4 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) +#error "SPI5 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_BDMA_STREAM) || \ + !defined(STM32_SPI_SPI6_TX_BDMA_STREAM)) +#error "SPI6 BDMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA streams.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI3 TX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI4 RX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI4 TX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI5 RX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM) +#error "Invalid DMA stream assigned to SPI5 TX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_BDMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_BDMA_STREAM) +#error "Invalid BDMA stream assigned to SPI6 RX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_BDMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_BDMA_STREAM) +#error "Invalid BDMA stream assigned to SPI6 TX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI6" +#endif + +#if STM32_SPI_USE_SPI1 || STM32_SPI_USE_SPI2 || STM32_SPI_USE_SPI3 || \ + STM32_SPI_USE_SPI4 || STM32_SPI_USE_SPI5 +#define STM32_SPI_DMA_REQUIRED +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif +#endif + +#if STM32_SPI_USE_SPI6 +#define STM32_SPI_BDMA_REQUIRED +#if !defined(STM32_BDMA_REQUIRED) +#define STM32_BDMA_REQUIRED +#endif +#endif + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD +#error "SPI_SELECT_MODE_LLD not supported by this driver" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#if (defined(STM32_SPI_DMA_REQUIRED) && \ + defined(STM32_SPI_BDMA_REQUIRED)) || defined(__DOXYGEN__) +#define spi_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /** DMA type for this instance.*/ \ + bool is_bdma; \ + /** Union of the RX DMA streams.*/ \ + union { \ + /* Receive DMA stream.*/ \ + const stm32_dma_stream_t *dma; \ + /* Receive BDMA stream.*/ \ + const stm32_bdma_stream_t *bdma; \ + } rx; \ + /* Union of the TX DMA streams.*/ \ + union { \ + /* Transmit DMA stream.*/ \ + const stm32_dma_stream_t *dma; \ + /* Transmit DMA stream.*/ \ + const stm32_bdma_stream_t *bdma; \ + } tx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode +#endif + +#if defined(STM32_SPI_DMA_REQUIRED) && !defined(STM32_SPI_BDMA_REQUIRED) +#define spi_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /** Union of the RX DMA streams.*/ \ + union { \ + /* Receive DMA stream.*/ \ + const stm32_dma_stream_t *dma; \ + } rx; \ + /* Union of the TX DMA streams.*/ \ + union { \ + /* Transmit DMA stream.*/ \ + const stm32_dma_stream_t *dma; \ + } tx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode +#endif + +#if !defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) +#define spi_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /** Union of the RX DMA streams.*/ \ + union { \ + /* Receive BDMA stream.*/ \ + const stm32_bdma_stream_t *bdma; \ + } rx; \ + /* Union of the TX DMA streams.*/ \ + union { \ + /* Transmit DMA stream.*/ \ + const stm32_bdma_stream_t *bdma; \ + } tx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode +#endif + +/** + * @brief Low level fields of the SPI configuration structure. + */ +#define spi_lld_config_fields \ + /* SPI CFG1 register initialization data.*/ \ + uint32_t cfg1; \ + /* SPI CFG2 register initialization data.*/ \ + uint32_t cfg2 + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) +extern SPIDriver SPID4; +#endif + +#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) +extern SPIDriver SPID5; +#endif + +#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) +extern SPIDriver SPID6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); +#endif + void spi_lld_ignore(SPIDriver *spip, size_t n); + void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) + void spi_lld_abort(SPIDriver *spip); +#endif + uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* HAL_SPI_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/driver.mk b/os/hal/ports/STM32/LLD/TIMv1/driver.mk index 032d75a2db..2fcf8995b3 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/driver.mk +++ b/os/hal/ports/STM32/LLD/TIMv1/driver.mk @@ -1,19 +1,19 @@ -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c - -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c -endif -ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c -endif -ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c + +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c +endif +ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c +endif +ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1 diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c index f7c449edb8..9571ad2967 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c @@ -1,1153 +1,1153 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_gpt_lld.c - * @brief STM32 GPT subsystem low level driver source. - * - * @addtogroup GPT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief GPTD1 driver identifier. - * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) -GPTDriver GPTD1; -#endif - -/** - * @brief GPTD2 driver identifier. - * @note The driver GPTD2 allocates the timer TIM2 when enabled. - */ -#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) -GPTDriver GPTD2; -#endif - -/** - * @brief GPTD3 driver identifier. - * @note The driver GPTD3 allocates the timer TIM3 when enabled. - */ -#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) -GPTDriver GPTD3; -#endif - -/** - * @brief GPTD4 driver identifier. - * @note The driver GPTD4 allocates the timer TIM4 when enabled. - */ -#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) -GPTDriver GPTD4; -#endif - -/** - * @brief GPTD5 driver identifier. - * @note The driver GPTD5 allocates the timer TIM5 when enabled. - */ -#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) -GPTDriver GPTD5; -#endif - -/** - * @brief GPTD6 driver identifier. - * @note The driver GPTD6 allocates the timer TIM6 when enabled. - */ -#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) -GPTDriver GPTD6; -#endif - -/** - * @brief GPTD7 driver identifier. - * @note The driver GPTD7 allocates the timer TIM7 when enabled. - */ -#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) -GPTDriver GPTD7; -#endif - -/** - * @brief GPTD8 driver identifier. - * @note The driver GPTD8 allocates the timer TIM8 when enabled. - */ -#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) -GPTDriver GPTD8; -#endif - -/** - * @brief GPTD9 driver identifier. - * @note The driver GPTD9 allocates the timer TIM9 when enabled. - */ -#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) -GPTDriver GPTD9; -#endif - -/** - * @brief GPTD10 driver identifier. - * @note The driver GPTD10 allocates the timer TIM10 when enabled. - */ -#if STM32_GPT_USE_TIM10 || defined(__DOXYGEN__) -GPTDriver GPTD10; -#endif - -/** - * @brief GPTD11 driver identifier. - * @note The driver GPTD11 allocates the timer TIM11 when enabled. - */ -#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) -GPTDriver GPTD11; -#endif - -/** - * @brief GPTD12 driver identifier. - * @note The driver GPTD12 allocates the timer TIM12 when enabled. - */ -#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) -GPTDriver GPTD12; -#endif - -/** - * @brief GPTD13 driver identifier. - * @note The driver GPTD13 allocates the timer TIM13 when enabled. - */ -#if STM32_GPT_USE_TIM13 || defined(__DOXYGEN__) -GPTDriver GPTD13; -#endif - -/** - * @brief GPTD14 driver identifier. - * @note The driver GPTD14 allocates the timer TIM14 when enabled. - */ -#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) -GPTDriver GPTD14; -#endif - -/** - * @brief GPTD15 driver identifier. - * @note The driver GPTD14 allocates the timer TIM14 when enabled. - */ -#if STM32_GPT_USE_TIM15 || defined(__DOXYGEN__) -GPTDriver GPTD15; -#endif - -/** - * @brief GPTD16 driver identifier. - * @note The driver GPTD14 allocates the timer TIM14 when enabled. - */ -#if STM32_GPT_USE_TIM16 || defined(__DOXYGEN__) -GPTDriver GPTD16; -#endif - -/** - * @brief GPTD17 driver identifier. - * @note The driver GPTD14 allocates the timer TIM14 when enabled. - */ -#if STM32_GPT_USE_TIM17 || defined(__DOXYGEN__) -GPTDriver GPTD17; -#endif - -/** - * @brief GPTD21 driver identifier. - * @note The driver GPTD21 allocates the timer TIM21 when enabled. - */ -#if STM32_GPT_USE_TIM21 || defined(__DOXYGEN__) -GPTDriver GPTD21; -#endif - -/** - * @brief GPTD22 driver identifier. - * @note The driver GPTD22 allocates the timer TIM22 when enabled. - */ -#if STM32_GPT_USE_TIM22 || defined(__DOXYGEN__) -GPTDriver GPTD22; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) -#if !defined(STM32_TIM1_SUPPRESS_ISR) -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM1 */ - -#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) -#if !defined(STM32_TIM2_SUPPRESS_ISR) -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM2 */ - -#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) -#if !defined(STM32_TIM3_SUPPRESS_ISR) -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM3 */ - -#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) -#if !defined(STM32_TIM4_SUPPRESS_ISR) -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM4 */ - -#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) -#if !defined(STM32_TIM5_SUPPRESS_ISR) -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM5 */ - -#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) -#if !defined(STM32_TIM6_SUPPRESS_ISR) -#if !defined(STM32_TIM6_HANDLER) -#error "STM32_TIM6_HANDLER not defined" -#endif -/** - * @brief TIM6 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM6_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM6 */ - -#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) -#if !defined(STM32_TIM7_SUPPRESS_ISR) -#if !defined(STM32_TIM7_HANDLER) -#error "STM32_TIM7_HANDLER not defined" -#endif -/** - * @brief TIM7 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM7_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM7 */ - -#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) -#if !defined(STM32_TIM8_SUPPRESS_ISR) -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM8 */ - -#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) -#if !defined(STM32_TIM9_SUPPRESS_ISR) -#error "TIM9 ISR not defined by platform" -#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM9 */ - -#if STM32_GPT_USE_TIM10 || defined(__DOXYGEN__) -#if !defined(STM32_TIM10_SUPPRESS_ISR) -#error "TIM10 ISR not defined by platform" -#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM10 */ - -#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) -#if !defined(STM32_TIM11_SUPPRESS_ISR) -#error "TIM11 ISR not defined by platform" -#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM11 */ - -#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) -#if !defined(STM32_TIM12_SUPPRESS_ISR) -#error "TIM12 ISR not defined by platform" -#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM12 */ - -#if STM32_GPT_USE_TIM13 || defined(__DOXYGEN__) -#if !defined(STM32_TIM13_SUPPRESS_ISR) -#error "TIM13 ISR not defined by platform" -#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM13 */ - -#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) -#if !defined(STM32_TIM14_SUPPRESS_ISR) -#error "TIM14 ISR not defined by platform" -#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM14 */ - -#if STM32_GPT_USE_TIM15 || defined(__DOXYGEN__) -#if !defined(STM32_TIM15_SUPPRESS_ISR) -#error "TIM15 ISR not defined by platform" -#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM15 */ - -#if STM32_GPT_USE_TIM16 || defined(__DOXYGEN__) -#if !defined(STM32_TIM16_SUPPRESS_ISR) -#error "TIM16 ISR not defined by platform" -#endif /* !defined(STM32_TIM16_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM16 */ - -#if STM32_GPT_USE_TIM17 || defined(__DOXYGEN__) -#if !defined(STM32_TIM17_SUPPRESS_ISR) -#error "TIM17 ISR not defined by platform" -#endif /* !defined(STM32_TIM17_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM17 */ - -#if STM32_GPT_USE_TIM21 || defined(__DOXYGEN__) -#if !defined(STM32_TIM21_SUPPRESS_ISR) -#if !defined(STM32_TIM21_HANDLER) -#error "STM32_TIM21_HANDLER not defined" -#endif -/** - * @brief TIM21 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM21_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD21); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM21 */ - -#if STM32_GPT_USE_TIM22 || defined(__DOXYGEN__) -#if !defined(STM32_TIM22_SUPPRESS_ISR) -#if !defined(STM32_TIM22_HANDLER) -#error "STM32_TIM22_HANDLER not defined" -#endif -/** - * @brief TIM22 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM22_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD22); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM22 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level GPT driver initialization. - * - * @notapi - */ -void gpt_lld_init(void) { - -#if STM32_GPT_USE_TIM1 - /* Driver initialization.*/ - GPTD1.tim = STM32_TIM1; - gptObjectInit(&GPTD1); -#endif - -#if STM32_GPT_USE_TIM2 - /* Driver initialization.*/ - GPTD2.tim = STM32_TIM2; - gptObjectInit(&GPTD2); -#endif - -#if STM32_GPT_USE_TIM3 - /* Driver initialization.*/ - GPTD3.tim = STM32_TIM3; - gptObjectInit(&GPTD3); -#endif - -#if STM32_GPT_USE_TIM4 - /* Driver initialization.*/ - GPTD4.tim = STM32_TIM4; - gptObjectInit(&GPTD4); -#endif - -#if STM32_GPT_USE_TIM5 - /* Driver initialization.*/ - GPTD5.tim = STM32_TIM5; - gptObjectInit(&GPTD5); -#endif - -#if STM32_GPT_USE_TIM6 - /* Driver initialization.*/ - GPTD6.tim = STM32_TIM6; - gptObjectInit(&GPTD6); -#endif - -#if STM32_GPT_USE_TIM7 - /* Driver initialization.*/ - GPTD7.tim = STM32_TIM7; - gptObjectInit(&GPTD7); -#endif - -#if STM32_GPT_USE_TIM8 - /* Driver initialization.*/ - GPTD8.tim = STM32_TIM8; - gptObjectInit(&GPTD8); -#endif - -#if STM32_GPT_USE_TIM9 - /* Driver initialization.*/ - GPTD9.tim = STM32_TIM9; - gptObjectInit(&GPTD9); -#endif - -#if STM32_GPT_USE_TIM10 - /* Driver initialization.*/ - GPTD10.tim = STM32_TIM10; - gptObjectInit(&GPTD10); -#endif - -#if STM32_GPT_USE_TIM11 - /* Driver initialization.*/ - GPTD11.tim = STM32_TIM11; - gptObjectInit(&GPTD11); -#endif - -#if STM32_GPT_USE_TIM12 - /* Driver initialization.*/ - GPTD12.tim = STM32_TIM12; - gptObjectInit(&GPTD12); -#endif - -#if STM32_GPT_USE_TIM13 - /* Driver initialization.*/ - GPTD13.tim = STM32_TIM13; - gptObjectInit(&GPTD13); -#endif - -#if STM32_GPT_USE_TIM14 - /* Driver initialization.*/ - GPTD14.tim = STM32_TIM14; - gptObjectInit(&GPTD14); -#endif - -#if STM32_GPT_USE_TIM15 - /* Driver initialization.*/ - GPTD15.tim = STM32_TIM15; - gptObjectInit(&GPTD15); -#endif - -#if STM32_GPT_USE_TIM16 - /* Driver initialization.*/ - GPTD16.tim = STM32_TIM16; - gptObjectInit(&GPTD16); -#endif - -#if STM32_GPT_USE_TIM17 - /* Driver initialization.*/ - GPTD17.tim = STM32_TIM17; - gptObjectInit(&GPTD17); -#endif - -#if STM32_GPT_USE_TIM21 - /* Driver initialization.*/ - GPTD21.tim = STM32_TIM21; - gptObjectInit(&GPTD21); -#endif - -#if STM32_GPT_USE_TIM22 - /* Driver initialization.*/ - GPTD22.tim = STM32_TIM22; - gptObjectInit(&GPTD22); -#endif -} - -/** - * @brief Configures and activates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_start(GPTDriver *gptp) { - uint16_t psc; - - if (gptp->state == GPT_STOP) { - /* Clock activation.*/ -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { - rccEnableTIM1(true); - rccResetTIM1(); -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM1CLK) - gptp->clock = STM32_TIM1CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { - rccEnableTIM2(true); - rccResetTIM2(); -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM2CLK) - gptp->clock = STM32_TIM2CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { - rccEnableTIM3(true); - rccResetTIM3(); -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM3CLK) - gptp->clock = STM32_TIM3CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { - rccEnableTIM4(true); - rccResetTIM4(); -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM4CLK) - gptp->clock = STM32_TIM4CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { - rccEnableTIM5(true); - rccResetTIM5(); -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM5CLK) - gptp->clock = STM32_TIM5CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { - rccEnableTIM6(true); - rccResetTIM6(); -#if !defined(STM32_TIM6_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM6CLK) - gptp->clock = STM32_TIM6CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { - rccEnableTIM7(true); - rccResetTIM7(); -#if !defined(STM32_TIM7_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM7CLK) - gptp->clock = STM32_TIM7CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { - rccEnableTIM8(true); - rccResetTIM8(); -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM8CLK) - gptp->clock = STM32_TIM8CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { - rccEnableTIM9(true); - rccResetTIM9(); -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM9CLK) - gptp->clock = STM32_TIM9CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM10 - if (&GPTD10 == gptp) { - rccEnableTIM10(true); - rccResetTIM10(); -#if !defined(STM32_TIM10_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM10_NUMBER, STM32_GPT_TIM10_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM10CLK) - gptp->clock = STM32_TIM10CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { - rccEnableTIM11(true); - rccResetTIM11(); -#if !defined(STM32_TIM11_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM11CLK) - gptp->clock = STM32_TIM11CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { - rccEnableTIM12(true); - rccResetTIM12(); -#if !defined(STM32_TIM12_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM12CLK) - gptp->clock = STM32_TIM12CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM13 - if (&GPTD13 == gptp) { - rccEnableTIM13(true); - rccResetTIM13(); -#if !defined(STM32_TIM13_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM13_NUMBER, STM32_GPT_TIM13_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM13CLK) - gptp->clock = STM32_TIM13CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { - rccEnableTIM14(true); - rccResetTIM14(); -#if !defined(STM32_TIM14_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM14CLK) - gptp->clock = STM32_TIM14CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM15 - if (&GPTD15 == gptp) { - rccEnableTIM15(true); - rccResetTIM15(); -#if defined(STM32_TIM15CLK) - gptp->clock = STM32_TIM15CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM16 - if (&GPTD16 == gptp) { - rccEnableTIM16(true); - rccResetTIM16(); -#if defined(STM32_TIM16CLK) - gptp->clock = STM32_TIM16CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM17 - if (&GPTD17 == gptp) { - rccEnableTIM17(true); - rccResetTIM17(); -#if defined(STM32_TIM17CLK) - gptp->clock = STM32_TIM17CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM21 - if (&GPTD21 == gptp) { - rccEnableTIM21(true); - rccResetTIM21(); -#if !defined(STM32_TIM21_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM21_NUMBER, STM32_GPT_TIM21_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM21CLK) - gptp->clock = STM32_TIM21CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM22 - if (&GPTD22 == gptp) { - rccEnableTIM22(true); - rccResetTIM22(); -#if !defined(STM32_TIM22_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM22_NUMBER, STM32_GPT_TIM22_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM22CLK) - gptp->clock = STM32_TIM22CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - } - - /* Prescaler value calculation.*/ - psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); - osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, - "invalid frequency"); - - /* Timer configuration.*/ - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->CR2 = gptp->config->cr2; - gptp->tim->PSC = psc; /* Prescaler value. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */ - ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Deactivates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop(GPTDriver *gptp) { - - if (gptp->state == GPT_READY) { - gptp->tim->CR1 = 0; /* Timer disabled. */ - gptp->tim->DIER = 0; /* All IRQs disabled. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM1_UP_NUMBER); -#endif - rccDisableTIM1(); - } -#endif - -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM2_NUMBER); -#endif - rccDisableTIM2(); - } -#endif - -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM3_NUMBER); -#endif - rccDisableTIM3(); - } -#endif - -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM4_NUMBER); -#endif - rccDisableTIM4(); - } -#endif - -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM5_NUMBER); -#endif - rccDisableTIM5(); - } -#endif - -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { -#if !defined(STM32_TIM6_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM6_NUMBER); -#endif - rccDisableTIM6(); - } -#endif - -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { -#if !defined(STM32_TIM7_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM7_NUMBER); -#endif - rccDisableTIM7(); - } -#endif - -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM8_UP_NUMBER); -#endif - rccDisableTIM8(); - } -#endif - -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM9_NUMBER); -#endif - rccDisableTIM9(); - } -#endif - -#if STM32_GPT_USE_TIM10 - if (&GPTD10 == gptp) { -#if !defined(STM32_TIM10_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM10_NUMBER); -#endif - rccDisableTIM10(); - } -#endif - -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { -#if !defined(STM32_TIM11_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM11_NUMBER); -#endif - rccDisableTIM11(); - } -#endif - -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { -#if !defined(STM32_TIM12_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM12_NUMBER); -#endif - rccDisableTIM12(); - } -#endif - -#if STM32_GPT_USE_TIM13 - if (&GPTD13 == gptp) { -#if !defined(STM32_TIM13_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM13_NUMBER); -#endif - rccDisableTIM13(); - } -#endif - -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { -#if !defined(STM32_TIM14_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM14_NUMBER); -#endif - rccDisableTIM14(); - } -#endif - -#if STM32_GPT_USE_TIM15 - if (&GPTD15 == gptp) { - rccDisableTIM15(); - } -#endif - -#if STM32_GPT_USE_TIM16 - if (&GPTD16 == gptp) { - rccDisableTIM16(); - } -#endif - -#if STM32_GPT_USE_TIM17 - if (&GPTD17 == gptp) { - rccDisableTIM17(); - } -#endif - -#if STM32_GPT_USE_TIM21 - if (&GPTD21 == gptp) { -#if !defined(STM32_TIM21_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM21_NUMBER); -#endif - rccDisableTIM21(); - } -#endif - -#if STM32_GPT_USE_TIM22 - if (&GPTD22 == gptp) { -#if !defined(STM32_TIM22_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM22_NUMBER); -#endif - rccDisableTIM22(); - } -#endif - } -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @notapi - */ -void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { - - gptp->tim->ARR = (uint32_t)(interval - 1U); /* Time constant. */ - gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - gptp->tim->CNT = 0; /* Reset counter. */ - - /* NOTE: After generating the UG event it takes several clock cycles before - SR bit 0 goes to 1. This is why the clearing of CNT has been inserted - before the clearing of SR, to give it some time.*/ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - if (NULL != gptp->config->callback) - gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/ - gptp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop_timer(GPTDriver *gptp) { - - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - - /* All interrupts disabled.*/ - gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Starts the timer in one shot mode and waits for completion. - * @details This function specifically polls the timer waiting for completion - * in order to not have extra delays caused by interrupt servicing, - * this function is only recommended for short delays. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @notapi - */ -void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { - - gptp->tim->ARR = (uint32_t)(interval - 1U); /* Time constant. */ - gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; - while (!(gptp->tim->SR & STM32_TIM_SR_UIF)) - ; - gptp->tim->SR = 0; /* Clear pending IRQs. */ -} - -/** - * @brief Shared IRQ handler. - * - * @param[in] gptp pointer to a @p GPTDriver object - * - * @notapi - */ -void gpt_lld_serve_interrupt(GPTDriver *gptp) { - uint32_t sr; - - sr = gptp->tim->SR; - sr &= gptp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - gptp->tim->SR = ~sr; - if ((sr & STM32_TIM_SR_UIF) != 0) { - _gpt_isr_invoke_cb(gptp); - } -} - -#endif /* HAL_USE_GPT */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_gpt_lld.c + * @brief STM32 GPT subsystem low level driver source. + * + * @addtogroup GPT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief GPTD1 driver identifier. + * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) +GPTDriver GPTD1; +#endif + +/** + * @brief GPTD2 driver identifier. + * @note The driver GPTD2 allocates the timer TIM2 when enabled. + */ +#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) +GPTDriver GPTD2; +#endif + +/** + * @brief GPTD3 driver identifier. + * @note The driver GPTD3 allocates the timer TIM3 when enabled. + */ +#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) +GPTDriver GPTD3; +#endif + +/** + * @brief GPTD4 driver identifier. + * @note The driver GPTD4 allocates the timer TIM4 when enabled. + */ +#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) +GPTDriver GPTD4; +#endif + +/** + * @brief GPTD5 driver identifier. + * @note The driver GPTD5 allocates the timer TIM5 when enabled. + */ +#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) +GPTDriver GPTD5; +#endif + +/** + * @brief GPTD6 driver identifier. + * @note The driver GPTD6 allocates the timer TIM6 when enabled. + */ +#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) +GPTDriver GPTD6; +#endif + +/** + * @brief GPTD7 driver identifier. + * @note The driver GPTD7 allocates the timer TIM7 when enabled. + */ +#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) +GPTDriver GPTD7; +#endif + +/** + * @brief GPTD8 driver identifier. + * @note The driver GPTD8 allocates the timer TIM8 when enabled. + */ +#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) +GPTDriver GPTD8; +#endif + +/** + * @brief GPTD9 driver identifier. + * @note The driver GPTD9 allocates the timer TIM9 when enabled. + */ +#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) +GPTDriver GPTD9; +#endif + +/** + * @brief GPTD10 driver identifier. + * @note The driver GPTD10 allocates the timer TIM10 when enabled. + */ +#if STM32_GPT_USE_TIM10 || defined(__DOXYGEN__) +GPTDriver GPTD10; +#endif + +/** + * @brief GPTD11 driver identifier. + * @note The driver GPTD11 allocates the timer TIM11 when enabled. + */ +#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) +GPTDriver GPTD11; +#endif + +/** + * @brief GPTD12 driver identifier. + * @note The driver GPTD12 allocates the timer TIM12 when enabled. + */ +#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) +GPTDriver GPTD12; +#endif + +/** + * @brief GPTD13 driver identifier. + * @note The driver GPTD13 allocates the timer TIM13 when enabled. + */ +#if STM32_GPT_USE_TIM13 || defined(__DOXYGEN__) +GPTDriver GPTD13; +#endif + +/** + * @brief GPTD14 driver identifier. + * @note The driver GPTD14 allocates the timer TIM14 when enabled. + */ +#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) +GPTDriver GPTD14; +#endif + +/** + * @brief GPTD15 driver identifier. + * @note The driver GPTD14 allocates the timer TIM14 when enabled. + */ +#if STM32_GPT_USE_TIM15 || defined(__DOXYGEN__) +GPTDriver GPTD15; +#endif + +/** + * @brief GPTD16 driver identifier. + * @note The driver GPTD14 allocates the timer TIM14 when enabled. + */ +#if STM32_GPT_USE_TIM16 || defined(__DOXYGEN__) +GPTDriver GPTD16; +#endif + +/** + * @brief GPTD17 driver identifier. + * @note The driver GPTD14 allocates the timer TIM14 when enabled. + */ +#if STM32_GPT_USE_TIM17 || defined(__DOXYGEN__) +GPTDriver GPTD17; +#endif + +/** + * @brief GPTD21 driver identifier. + * @note The driver GPTD21 allocates the timer TIM21 when enabled. + */ +#if STM32_GPT_USE_TIM21 || defined(__DOXYGEN__) +GPTDriver GPTD21; +#endif + +/** + * @brief GPTD22 driver identifier. + * @note The driver GPTD22 allocates the timer TIM22 when enabled. + */ +#if STM32_GPT_USE_TIM22 || defined(__DOXYGEN__) +GPTDriver GPTD22; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) +#if !defined(STM32_TIM1_SUPPRESS_ISR) +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM1 */ + +#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) +#if !defined(STM32_TIM2_SUPPRESS_ISR) +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM2 */ + +#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) +#if !defined(STM32_TIM3_SUPPRESS_ISR) +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM3 */ + +#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) +#if !defined(STM32_TIM4_SUPPRESS_ISR) +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM4 */ + +#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) +#if !defined(STM32_TIM5_SUPPRESS_ISR) +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM5 */ + +#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) +#if !defined(STM32_TIM6_SUPPRESS_ISR) +#if !defined(STM32_TIM6_HANDLER) +#error "STM32_TIM6_HANDLER not defined" +#endif +/** + * @brief TIM6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM6_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM6 */ + +#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) +#if !defined(STM32_TIM7_SUPPRESS_ISR) +#if !defined(STM32_TIM7_HANDLER) +#error "STM32_TIM7_HANDLER not defined" +#endif +/** + * @brief TIM7 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM7_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM7 */ + +#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) +#if !defined(STM32_TIM8_SUPPRESS_ISR) +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM8 */ + +#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) +#if !defined(STM32_TIM9_SUPPRESS_ISR) +#error "TIM9 ISR not defined by platform" +#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM9 */ + +#if STM32_GPT_USE_TIM10 || defined(__DOXYGEN__) +#if !defined(STM32_TIM10_SUPPRESS_ISR) +#error "TIM10 ISR not defined by platform" +#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM10 */ + +#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) +#if !defined(STM32_TIM11_SUPPRESS_ISR) +#error "TIM11 ISR not defined by platform" +#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM11 */ + +#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) +#if !defined(STM32_TIM12_SUPPRESS_ISR) +#error "TIM12 ISR not defined by platform" +#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM12 */ + +#if STM32_GPT_USE_TIM13 || defined(__DOXYGEN__) +#if !defined(STM32_TIM13_SUPPRESS_ISR) +#error "TIM13 ISR not defined by platform" +#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM13 */ + +#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) +#if !defined(STM32_TIM14_SUPPRESS_ISR) +#error "TIM14 ISR not defined by platform" +#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM14 */ + +#if STM32_GPT_USE_TIM15 || defined(__DOXYGEN__) +#if !defined(STM32_TIM15_SUPPRESS_ISR) +#error "TIM15 ISR not defined by platform" +#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM15 */ + +#if STM32_GPT_USE_TIM16 || defined(__DOXYGEN__) +#if !defined(STM32_TIM16_SUPPRESS_ISR) +#error "TIM16 ISR not defined by platform" +#endif /* !defined(STM32_TIM16_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM16 */ + +#if STM32_GPT_USE_TIM17 || defined(__DOXYGEN__) +#if !defined(STM32_TIM17_SUPPRESS_ISR) +#error "TIM17 ISR not defined by platform" +#endif /* !defined(STM32_TIM17_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM17 */ + +#if STM32_GPT_USE_TIM21 || defined(__DOXYGEN__) +#if !defined(STM32_TIM21_SUPPRESS_ISR) +#if !defined(STM32_TIM21_HANDLER) +#error "STM32_TIM21_HANDLER not defined" +#endif +/** + * @brief TIM21 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM21_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD21); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM21 */ + +#if STM32_GPT_USE_TIM22 || defined(__DOXYGEN__) +#if !defined(STM32_TIM22_SUPPRESS_ISR) +#if !defined(STM32_TIM22_HANDLER) +#error "STM32_TIM22_HANDLER not defined" +#endif +/** + * @brief TIM22 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM22_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD22); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM22 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level GPT driver initialization. + * + * @notapi + */ +void gpt_lld_init(void) { + +#if STM32_GPT_USE_TIM1 + /* Driver initialization.*/ + GPTD1.tim = STM32_TIM1; + gptObjectInit(&GPTD1); +#endif + +#if STM32_GPT_USE_TIM2 + /* Driver initialization.*/ + GPTD2.tim = STM32_TIM2; + gptObjectInit(&GPTD2); +#endif + +#if STM32_GPT_USE_TIM3 + /* Driver initialization.*/ + GPTD3.tim = STM32_TIM3; + gptObjectInit(&GPTD3); +#endif + +#if STM32_GPT_USE_TIM4 + /* Driver initialization.*/ + GPTD4.tim = STM32_TIM4; + gptObjectInit(&GPTD4); +#endif + +#if STM32_GPT_USE_TIM5 + /* Driver initialization.*/ + GPTD5.tim = STM32_TIM5; + gptObjectInit(&GPTD5); +#endif + +#if STM32_GPT_USE_TIM6 + /* Driver initialization.*/ + GPTD6.tim = STM32_TIM6; + gptObjectInit(&GPTD6); +#endif + +#if STM32_GPT_USE_TIM7 + /* Driver initialization.*/ + GPTD7.tim = STM32_TIM7; + gptObjectInit(&GPTD7); +#endif + +#if STM32_GPT_USE_TIM8 + /* Driver initialization.*/ + GPTD8.tim = STM32_TIM8; + gptObjectInit(&GPTD8); +#endif + +#if STM32_GPT_USE_TIM9 + /* Driver initialization.*/ + GPTD9.tim = STM32_TIM9; + gptObjectInit(&GPTD9); +#endif + +#if STM32_GPT_USE_TIM10 + /* Driver initialization.*/ + GPTD10.tim = STM32_TIM10; + gptObjectInit(&GPTD10); +#endif + +#if STM32_GPT_USE_TIM11 + /* Driver initialization.*/ + GPTD11.tim = STM32_TIM11; + gptObjectInit(&GPTD11); +#endif + +#if STM32_GPT_USE_TIM12 + /* Driver initialization.*/ + GPTD12.tim = STM32_TIM12; + gptObjectInit(&GPTD12); +#endif + +#if STM32_GPT_USE_TIM13 + /* Driver initialization.*/ + GPTD13.tim = STM32_TIM13; + gptObjectInit(&GPTD13); +#endif + +#if STM32_GPT_USE_TIM14 + /* Driver initialization.*/ + GPTD14.tim = STM32_TIM14; + gptObjectInit(&GPTD14); +#endif + +#if STM32_GPT_USE_TIM15 + /* Driver initialization.*/ + GPTD15.tim = STM32_TIM15; + gptObjectInit(&GPTD15); +#endif + +#if STM32_GPT_USE_TIM16 + /* Driver initialization.*/ + GPTD16.tim = STM32_TIM16; + gptObjectInit(&GPTD16); +#endif + +#if STM32_GPT_USE_TIM17 + /* Driver initialization.*/ + GPTD17.tim = STM32_TIM17; + gptObjectInit(&GPTD17); +#endif + +#if STM32_GPT_USE_TIM21 + /* Driver initialization.*/ + GPTD21.tim = STM32_TIM21; + gptObjectInit(&GPTD21); +#endif + +#if STM32_GPT_USE_TIM22 + /* Driver initialization.*/ + GPTD22.tim = STM32_TIM22; + gptObjectInit(&GPTD22); +#endif +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_start(GPTDriver *gptp) { + uint16_t psc; + + if (gptp->state == GPT_STOP) { + /* Clock activation.*/ +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { + rccEnableTIM1(true); + rccResetTIM1(); +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM1CLK) + gptp->clock = STM32_TIM1CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { + rccEnableTIM2(true); + rccResetTIM2(); +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM2CLK) + gptp->clock = STM32_TIM2CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { + rccEnableTIM3(true); + rccResetTIM3(); +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM3CLK) + gptp->clock = STM32_TIM3CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { + rccEnableTIM4(true); + rccResetTIM4(); +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM4CLK) + gptp->clock = STM32_TIM4CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { + rccEnableTIM5(true); + rccResetTIM5(); +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM5CLK) + gptp->clock = STM32_TIM5CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { + rccEnableTIM6(true); + rccResetTIM6(); +#if !defined(STM32_TIM6_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM6CLK) + gptp->clock = STM32_TIM6CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { + rccEnableTIM7(true); + rccResetTIM7(); +#if !defined(STM32_TIM7_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM7CLK) + gptp->clock = STM32_TIM7CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { + rccEnableTIM8(true); + rccResetTIM8(); +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM8CLK) + gptp->clock = STM32_TIM8CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { + rccEnableTIM9(true); + rccResetTIM9(); +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM9CLK) + gptp->clock = STM32_TIM9CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM10 + if (&GPTD10 == gptp) { + rccEnableTIM10(true); + rccResetTIM10(); +#if !defined(STM32_TIM10_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM10_NUMBER, STM32_GPT_TIM10_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM10CLK) + gptp->clock = STM32_TIM10CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { + rccEnableTIM11(true); + rccResetTIM11(); +#if !defined(STM32_TIM11_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM11CLK) + gptp->clock = STM32_TIM11CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { + rccEnableTIM12(true); + rccResetTIM12(); +#if !defined(STM32_TIM12_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM12CLK) + gptp->clock = STM32_TIM12CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM13 + if (&GPTD13 == gptp) { + rccEnableTIM13(true); + rccResetTIM13(); +#if !defined(STM32_TIM13_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM13_NUMBER, STM32_GPT_TIM13_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM13CLK) + gptp->clock = STM32_TIM13CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { + rccEnableTIM14(true); + rccResetTIM14(); +#if !defined(STM32_TIM14_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM14CLK) + gptp->clock = STM32_TIM14CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM15 + if (&GPTD15 == gptp) { + rccEnableTIM15(true); + rccResetTIM15(); +#if defined(STM32_TIM15CLK) + gptp->clock = STM32_TIM15CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM16 + if (&GPTD16 == gptp) { + rccEnableTIM16(true); + rccResetTIM16(); +#if defined(STM32_TIM16CLK) + gptp->clock = STM32_TIM16CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM17 + if (&GPTD17 == gptp) { + rccEnableTIM17(true); + rccResetTIM17(); +#if defined(STM32_TIM17CLK) + gptp->clock = STM32_TIM17CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM21 + if (&GPTD21 == gptp) { + rccEnableTIM21(true); + rccResetTIM21(); +#if !defined(STM32_TIM21_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM21_NUMBER, STM32_GPT_TIM21_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM21CLK) + gptp->clock = STM32_TIM21CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM22 + if (&GPTD22 == gptp) { + rccEnableTIM22(true); + rccResetTIM22(); +#if !defined(STM32_TIM22_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM22_NUMBER, STM32_GPT_TIM22_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM22CLK) + gptp->clock = STM32_TIM22CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + } + + /* Prescaler value calculation.*/ + psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); + osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, + "invalid frequency"); + + /* Timer configuration.*/ + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->CR2 = gptp->config->cr2; + gptp->tim->PSC = psc; /* Prescaler value. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */ + ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop(GPTDriver *gptp) { + + if (gptp->state == GPT_READY) { + gptp->tim->CR1 = 0; /* Timer disabled. */ + gptp->tim->DIER = 0; /* All IRQs disabled. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM1_UP_NUMBER); +#endif + rccDisableTIM1(); + } +#endif + +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM2_NUMBER); +#endif + rccDisableTIM2(); + } +#endif + +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM3_NUMBER); +#endif + rccDisableTIM3(); + } +#endif + +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM4_NUMBER); +#endif + rccDisableTIM4(); + } +#endif + +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM5_NUMBER); +#endif + rccDisableTIM5(); + } +#endif + +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { +#if !defined(STM32_TIM6_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM6_NUMBER); +#endif + rccDisableTIM6(); + } +#endif + +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { +#if !defined(STM32_TIM7_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM7_NUMBER); +#endif + rccDisableTIM7(); + } +#endif + +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM8_UP_NUMBER); +#endif + rccDisableTIM8(); + } +#endif + +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM9_NUMBER); +#endif + rccDisableTIM9(); + } +#endif + +#if STM32_GPT_USE_TIM10 + if (&GPTD10 == gptp) { +#if !defined(STM32_TIM10_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM10_NUMBER); +#endif + rccDisableTIM10(); + } +#endif + +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { +#if !defined(STM32_TIM11_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM11_NUMBER); +#endif + rccDisableTIM11(); + } +#endif + +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { +#if !defined(STM32_TIM12_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM12_NUMBER); +#endif + rccDisableTIM12(); + } +#endif + +#if STM32_GPT_USE_TIM13 + if (&GPTD13 == gptp) { +#if !defined(STM32_TIM13_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM13_NUMBER); +#endif + rccDisableTIM13(); + } +#endif + +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { +#if !defined(STM32_TIM14_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM14_NUMBER); +#endif + rccDisableTIM14(); + } +#endif + +#if STM32_GPT_USE_TIM15 + if (&GPTD15 == gptp) { + rccDisableTIM15(); + } +#endif + +#if STM32_GPT_USE_TIM16 + if (&GPTD16 == gptp) { + rccDisableTIM16(); + } +#endif + +#if STM32_GPT_USE_TIM17 + if (&GPTD17 == gptp) { + rccDisableTIM17(); + } +#endif + +#if STM32_GPT_USE_TIM21 + if (&GPTD21 == gptp) { +#if !defined(STM32_TIM21_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM21_NUMBER); +#endif + rccDisableTIM21(); + } +#endif + +#if STM32_GPT_USE_TIM22 + if (&GPTD22 == gptp) { +#if !defined(STM32_TIM22_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM22_NUMBER); +#endif + rccDisableTIM22(); + } +#endif + } +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @notapi + */ +void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { + + gptp->tim->ARR = (uint32_t)(interval - 1U); /* Time constant. */ + gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + gptp->tim->CNT = 0; /* Reset counter. */ + + /* NOTE: After generating the UG event it takes several clock cycles before + SR bit 0 goes to 1. This is why the clearing of CNT has been inserted + before the clearing of SR, to give it some time.*/ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + if (NULL != gptp->config->callback) + gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/ + gptp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop_timer(GPTDriver *gptp) { + + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + + /* All interrupts disabled.*/ + gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Starts the timer in one shot mode and waits for completion. + * @details This function specifically polls the timer waiting for completion + * in order to not have extra delays caused by interrupt servicing, + * this function is only recommended for short delays. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @notapi + */ +void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { + + gptp->tim->ARR = (uint32_t)(interval - 1U); /* Time constant. */ + gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; + while (!(gptp->tim->SR & STM32_TIM_SR_UIF)) + ; + gptp->tim->SR = 0; /* Clear pending IRQs. */ +} + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + * + * @notapi + */ +void gpt_lld_serve_interrupt(GPTDriver *gptp) { + uint32_t sr; + + sr = gptp->tim->SR; + sr &= gptp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + gptp->tim->SR = ~sr; + if ((sr & STM32_TIM_SR_UIF) != 0) { + _gpt_isr_invoke_cb(gptp); + } +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h index 1fbdea3feb..631ca191bd 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h @@ -1,980 +1,980 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_gpt_lld.h - * @brief STM32 GPT subsystem low level driver header. - * - * @addtogroup GPT - * @{ - */ - -#ifndef HAL_GPT_LLD_H -#define HAL_GPT_LLD_H - -#include "stm32_tim.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief GPTD1 driver enable switch. - * @details If set to @p TRUE the support for GPTD1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM1 FALSE -#endif - -/** - * @brief GPTD2 driver enable switch. - * @details If set to @p TRUE the support for GPTD2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM2 FALSE -#endif - -/** - * @brief GPTD3 driver enable switch. - * @details If set to @p TRUE the support for GPTD3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM3 FALSE -#endif - -/** - * @brief GPTD4 driver enable switch. - * @details If set to @p TRUE the support for GPTD4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM4 FALSE -#endif - -/** - * @brief GPTD5 driver enable switch. - * @details If set to @p TRUE the support for GPTD5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM5 FALSE -#endif - -/** - * @brief GPTD6 driver enable switch. - * @details If set to @p TRUE the support for GPTD6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM6 FALSE -#endif - -/** - * @brief GPTD7 driver enable switch. - * @details If set to @p TRUE the support for GPTD7 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM7 FALSE -#endif - -/** - * @brief GPTD8 driver enable switch. - * @details If set to @p TRUE the support for GPTD8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM8 FALSE -#endif - -/** - * @brief GPTD9 driver enable switch. - * @details If set to @p TRUE the support for GPTD9 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM9 FALSE -#endif - -/** - * @brief GPTD10 driver enable switch. - * @details If set to @p TRUE the support for GPTD10 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM10) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM10 FALSE -#endif - -/** - * @brief GPTD11 driver enable switch. - * @details If set to @p TRUE the support for GPTD11 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM11 FALSE -#endif - -/** - * @brief GPTD12 driver enable switch. - * @details If set to @p TRUE the support for GPTD12 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM12 FALSE -#endif - -/** - * @brief GPTD13 driver enable switch. - * @details If set to @p TRUE the support for GPTD13 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM13) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM13 FALSE -#endif - -/** - * @brief GPTD14 driver enable switch. - * @details If set to @p TRUE the support for GPTD14 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM14 FALSE -#endif - -/** - * @brief GPTD14 driver enable switch. - * @details If set to @p TRUE the support for GPTD15 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM15) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM15 FALSE -#endif - -/** - * @brief GPTD14 driver enable switch. - * @details If set to @p TRUE the support for GPTD16 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM16) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM16 FALSE -#endif - -/** - * @brief GPTD14 driver enable switch. - * @details If set to @p TRUE the support for GPTD17 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM17) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM17 FALSE -#endif - -/** - * @brief GPTD21 driver enable switch. - * @details If set to @p TRUE the support for GPTD21 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM21) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM21 FALSE -#endif - -/** - * @brief GPTD22 driver enable switch. - * @details If set to @p TRUE the support for GPTD22 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_GPT_USE_TIM22) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM22 FALSE -#endif - -/** - * @brief GPTD1 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD2 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD3 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD4 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD5 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD6 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD7 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD8 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD9 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD10 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM10_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD11 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD12 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM12_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD13 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM13_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD14 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM14_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD15 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM15_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD16 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM16_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM16_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD17 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM17_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM17_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD21 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM21_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD22 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM22_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_TIM1) -#define STM32_HAS_TIM1 FALSE -#endif - -#if !defined(STM32_HAS_TIM2) -#define STM32_HAS_TIM2 FALSE -#endif - -#if !defined(STM32_HAS_TIM3) -#define STM32_HAS_TIM3 FALSE -#endif - -#if !defined(STM32_HAS_TIM4) -#define STM32_HAS_TIM4 FALSE -#endif - -#if !defined(STM32_HAS_TIM5) -#define STM32_HAS_TIM5 FALSE -#endif - -#if !defined(STM32_HAS_TIM6) -#define STM32_HAS_TIM6 FALSE -#endif - -#if !defined(STM32_HAS_TIM7) -#define STM32_HAS_TIM7 FALSE -#endif - -#if !defined(STM32_HAS_TIM8) -#define STM32_HAS_TIM8 FALSE -#endif - -#if !defined(STM32_HAS_TIM9) -#define STM32_HAS_TIM9 FALSE -#endif - -#if !defined(STM32_HAS_TIM10) -#define STM32_HAS_TIM10 FALSE -#endif - -#if !defined(STM32_HAS_TIM11) -#define STM32_HAS_TIM11 FALSE -#endif - -#if !defined(STM32_HAS_TIM12) -#define STM32_HAS_TIM12 FALSE -#endif - -#if !defined(STM32_HAS_TIM13) -#define STM32_HAS_TIM13 FALSE -#endif - -#if !defined(STM32_HAS_TIM14) -#define STM32_HAS_TIM14 FALSE -#endif - -#if !defined(STM32_HAS_TIM15) -#define STM32_HAS_TIM15 FALSE -#endif - -#if !defined(STM32_HAS_TIM16) -#define STM32_HAS_TIM16 FALSE -#endif - -#if !defined(STM32_HAS_TIM17) -#define STM32_HAS_TIM17 FALSE -#endif - -#if !defined(STM32_HAS_TIM21) -#define STM32_HAS_TIM21 FALSE -#endif - -#if !defined(STM32_HAS_TIM22) -#define STM32_HAS_TIM22 FALSE -#endif - -#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6 -#error "TIM6 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7 -#error "TIM7 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM10 && !STM32_HAS_TIM10 -#error "TIM10 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11 -#error "TIM11 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12 -#error "TIM12 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM13 && !STM32_HAS_TIM13 -#error "TIM13 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14 -#error "TIM14 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM15 && !STM32_HAS_TIM15 -#error "TIM15 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM16 && !STM32_HAS_TIM16 -#error "TIM16 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM17 && !STM32_HAS_TIM17 -#error "TIM17 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM21 && !STM32_HAS_TIM21 -#error "TIM21 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM22 && !STM32_HAS_TIM22 -#error "TIM22 not present in the selected device" -#endif - -#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \ - !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \ - !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \ - !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \ - !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM10 && \ - !STM32_GPT_USE_TIM11 && !STM32_GPT_USE_TIM12 && \ - !STM32_GPT_USE_TIM13 && !STM32_GPT_USE_TIM14 && \ - !STM32_GPT_USE_TIM15 && !STM32_GPT_USE_TIM16 && \ - !STM32_GPT_USE_TIM17 && \ - !STM32_GPT_USE_TIM21 && !STM32_GPT_USE_TIM22 -#error "GPT driver activated but no TIM peripheral assigned" -#endif - -/* Checks on allocation of TIMx units.*/ -#if STM32_GPT_USE_TIM1 -#if defined(STM32_TIM1_IS_USED) -#error "GPTD1 requires TIM1 but the timer is already used" -#else -#define STM32_TIM1_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM2 -#if defined(STM32_TIM2_IS_USED) -#error "GPTD2 requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM3 -#if defined(STM32_TIM3_IS_USED) -#error "GPTD3 requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM4 -#if defined(STM32_TIM4_IS_USED) -#error "GPTD4 requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM5 -#if defined(STM32_TIM5_IS_USED) -#error "GPTD5 requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM6 -#if defined(STM32_TIM6_IS_USED) -#error "GPTD6 requires TIM6 but the timer is already used" -#else -#define STM32_TIM6_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM7 -#if defined(STM32_TIM7_IS_USED) -#error "GPTD7 requires TIM7 but the timer is already used" -#else -#define STM32_TIM7_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM8 -#if defined(STM32_TIM8_IS_USED) -#error "GPTD8 requires TIM8 but the timer is already used" -#else -#define STM32_TIM8_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM9 -#if defined(STM32_TIM9_IS_USED) -#error "GPTD9 requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM10 -#if defined(STM32_TIM10_IS_USED) -#error "GPTD10 requires TIM10 but the timer is already used" -#else -#define STM32_TIM10_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM11 -#if defined(STM32_TIM11_IS_USED) -#error "GPTD11 requires TIM11 but the timer is already used" -#else -#define STM32_TIM11_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM12 -#if defined(STM32_TIM12_IS_USED) -#error "GPTD12 requires TIM12 but the timer is already used" -#else -#define STM32_TIM12_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM13 -#if defined(STM32_TIM13_IS_USED) -#error "GPTD13 requires TIM13 but the timer is already used" -#else -#define STM32_TIM13_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM14 -#if defined(STM32_TIM14_IS_USED) -#error "GPTD14 requires TIM14 but the timer is already used" -#else -#define STM32_TIM14_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM15 -#if defined(STM32_TIM15_IS_USED) -#error "GPTD14 requires TIM15 but the timer is already used" -#else -#define STM32_TIM15_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM16 -#if defined(STM32_TIM16_IS_USED) -#error "GPTD14 requires TIM16 but the timer is already used" -#else -#define STM32_TIM16_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM17 -#if defined(STM32_TIM17_IS_USED) -#error "GPTD14 requires TIM17 but the timer is already used" -#else -#define STM32_TIM17_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM21 -#if defined(STM32_TIM21_IS_USED) -#error "GPTD21 requires TIM21 but the timer is already used" -#else -#define STM32_TIM21_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM22 -#if defined(STM32_TIM22_IS_USED) -#error "GPTD22 requires TIM22 but the timer is already used" -#else -#define STM32_TIM22_IS_USED -#endif -#endif - -/* IRQ priority checks.*/ -#if STM32_GPT_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_GPT_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_GPT_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_GPT_USE_TIM4 && !defined(STM32_TIM_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_GPT_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_GPT_USE_TIM6 && !defined(STM32_TIM6_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM6" -#endif - -#if STM32_GPT_USE_TIM7 && !defined(STM32_TIM7_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM7" -#endif - -#if STM32_GPT_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_GPT_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -#if STM32_GPT_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM10_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM10" -#endif - -#if STM32_GPT_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM11" -#endif - -#if STM32_GPT_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM12" -#endif - -#if STM32_GPT_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM13_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM13" -#endif - -#if STM32_GPT_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM14" -#endif - -#if STM32_GPT_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM15_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM15" -#endif - -#if STM32_GPT_USE_TIM16 && !defined(STM32_TIM16_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM16_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM16" -#endif - -#if STM32_GPT_USE_TIM17 && !defined(STM32_TIM17_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM17_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM17" -#endif - -#if STM32_GPT_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM21_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM21" -#endif - -#if STM32_GPT_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM22_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM22" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief GPT frequency type. - */ -typedef uint32_t gptfreq_t; - -/** - * @brief GPT counter type. - */ -typedef uint32_t gptcnt_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - gptfreq_t frequency; - /** - * @brief Timer callback pointer. - * @note This callback is invoked on GPT counter events. - * @note This callback can be set to @p NULL but in that case the - * one-shot mode cannot be used. - */ - gptcallback_t callback; - /* End of the mandatory fields.*/ - /** - * @brief TIM CR2 register initialization data. - * @note The value of this field should normally be equal to zero. - */ - uint32_t cr2; - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} GPTConfig; - -/** - * @brief Structure representing a GPT driver. - */ -struct GPTDriver { - /** - * @brief Driver state. - */ - gptstate_t state; - /** - * @brief Current configuration data. - */ - const GPTConfig *config; -#if defined(GPT_DRIVER_EXT_FIELDS) - GPT_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the interval of GPT peripheral. - * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must be running in continuous mode. - * @post The GPT unit interval is changed to the new value. - * @note The function has effect at the next cycle start. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @param[in] interval new cycle time in timer ticks - * - * @notapi - */ -#define gpt_lld_change_interval(gptp, interval) \ - ((gptp)->tim->ARR = (uint32_t)((interval) - 1U)) - -/** - * @brief Returns the interval of GPT peripheral. - * @pre The GPT unit must be running in continuous mode. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @return The current interval. - * - * @notapi - */ -#define gpt_lld_get_interval(gptp) ((gptcnt_t)((gptp)->tim->ARR + 1U)) - -/** - * @brief Returns the counter value of GPT peripheral. - * @pre The GPT unit must be running in continuous mode. - * @note The nature of the counter is not defined, it may count upward - * or downward, it could be continuously running or not. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @return The current counter value. - * - * @notapi - */ -#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->tim->CNT) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__) -extern GPTDriver GPTD1; -#endif - -#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__) -extern GPTDriver GPTD2; -#endif - -#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__) -extern GPTDriver GPTD3; -#endif - -#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__) -extern GPTDriver GPTD4; -#endif - -#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__) -extern GPTDriver GPTD5; -#endif - -#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__) -extern GPTDriver GPTD6; -#endif - -#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__) -extern GPTDriver GPTD7; -#endif - -#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__) -extern GPTDriver GPTD8; -#endif - -#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__) -extern GPTDriver GPTD9; -#endif - -#if STM32_GPT_USE_TIM10 && !defined(__DOXYGEN__) -extern GPTDriver GPTD10; -#endif - -#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__) -extern GPTDriver GPTD11; -#endif - -#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__) -extern GPTDriver GPTD12; -#endif - -#if STM32_GPT_USE_TIM13 && !defined(__DOXYGEN__) -extern GPTDriver GPTD13; -#endif - -#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__) -extern GPTDriver GPTD14; -#endif - -#if STM32_GPT_USE_TIM15 && !defined(__DOXYGEN__) -extern GPTDriver GPTD15; -#endif - -#if STM32_GPT_USE_TIM16 && !defined(__DOXYGEN__) -extern GPTDriver GPTD16; -#endif - -#if STM32_GPT_USE_TIM17 && !defined(__DOXYGEN__) -extern GPTDriver GPTD17; -#endif - -#if STM32_GPT_USE_TIM21 && !defined(__DOXYGEN__) -extern GPTDriver GPTD21; -#endif - -#if STM32_GPT_USE_TIM22 && !defined(__DOXYGEN__) -extern GPTDriver GPTD22; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void gpt_lld_init(void); - void gpt_lld_start(GPTDriver *gptp); - void gpt_lld_stop(GPTDriver *gptp); - void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); - void gpt_lld_stop_timer(GPTDriver *gptp); - void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); - void gpt_lld_serve_interrupt(GPTDriver *gptp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_GPT */ - -#endif /* HAL_GPT_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_gpt_lld.h + * @brief STM32 GPT subsystem low level driver header. + * + * @addtogroup GPT + * @{ + */ + +#ifndef HAL_GPT_LLD_H +#define HAL_GPT_LLD_H + +#include "stm32_tim.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief GPTD1 driver enable switch. + * @details If set to @p TRUE the support for GPTD1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM1 FALSE +#endif + +/** + * @brief GPTD2 driver enable switch. + * @details If set to @p TRUE the support for GPTD2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM2 FALSE +#endif + +/** + * @brief GPTD3 driver enable switch. + * @details If set to @p TRUE the support for GPTD3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM3 FALSE +#endif + +/** + * @brief GPTD4 driver enable switch. + * @details If set to @p TRUE the support for GPTD4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM4 FALSE +#endif + +/** + * @brief GPTD5 driver enable switch. + * @details If set to @p TRUE the support for GPTD5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM5 FALSE +#endif + +/** + * @brief GPTD6 driver enable switch. + * @details If set to @p TRUE the support for GPTD6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM6 FALSE +#endif + +/** + * @brief GPTD7 driver enable switch. + * @details If set to @p TRUE the support for GPTD7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM7 FALSE +#endif + +/** + * @brief GPTD8 driver enable switch. + * @details If set to @p TRUE the support for GPTD8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM8 FALSE +#endif + +/** + * @brief GPTD9 driver enable switch. + * @details If set to @p TRUE the support for GPTD9 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM9 FALSE +#endif + +/** + * @brief GPTD10 driver enable switch. + * @details If set to @p TRUE the support for GPTD10 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM10) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM10 FALSE +#endif + +/** + * @brief GPTD11 driver enable switch. + * @details If set to @p TRUE the support for GPTD11 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM11 FALSE +#endif + +/** + * @brief GPTD12 driver enable switch. + * @details If set to @p TRUE the support for GPTD12 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM12 FALSE +#endif + +/** + * @brief GPTD13 driver enable switch. + * @details If set to @p TRUE the support for GPTD13 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM13) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM13 FALSE +#endif + +/** + * @brief GPTD14 driver enable switch. + * @details If set to @p TRUE the support for GPTD14 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM14 FALSE +#endif + +/** + * @brief GPTD14 driver enable switch. + * @details If set to @p TRUE the support for GPTD15 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM15) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM15 FALSE +#endif + +/** + * @brief GPTD14 driver enable switch. + * @details If set to @p TRUE the support for GPTD16 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM16) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM16 FALSE +#endif + +/** + * @brief GPTD14 driver enable switch. + * @details If set to @p TRUE the support for GPTD17 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM17) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM17 FALSE +#endif + +/** + * @brief GPTD21 driver enable switch. + * @details If set to @p TRUE the support for GPTD21 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM21) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM21 FALSE +#endif + +/** + * @brief GPTD22 driver enable switch. + * @details If set to @p TRUE the support for GPTD22 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_GPT_USE_TIM22) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM22 FALSE +#endif + +/** + * @brief GPTD1 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD2 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD3 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD4 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD5 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD6 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD7 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD8 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD9 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD10 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM10_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD11 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD12 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD13 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM13_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD14 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD15 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM15_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD16 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM16_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM16_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD17 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM17_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM17_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD21 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM21_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD22 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM22_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_TIM1) +#define STM32_HAS_TIM1 FALSE +#endif + +#if !defined(STM32_HAS_TIM2) +#define STM32_HAS_TIM2 FALSE +#endif + +#if !defined(STM32_HAS_TIM3) +#define STM32_HAS_TIM3 FALSE +#endif + +#if !defined(STM32_HAS_TIM4) +#define STM32_HAS_TIM4 FALSE +#endif + +#if !defined(STM32_HAS_TIM5) +#define STM32_HAS_TIM5 FALSE +#endif + +#if !defined(STM32_HAS_TIM6) +#define STM32_HAS_TIM6 FALSE +#endif + +#if !defined(STM32_HAS_TIM7) +#define STM32_HAS_TIM7 FALSE +#endif + +#if !defined(STM32_HAS_TIM8) +#define STM32_HAS_TIM8 FALSE +#endif + +#if !defined(STM32_HAS_TIM9) +#define STM32_HAS_TIM9 FALSE +#endif + +#if !defined(STM32_HAS_TIM10) +#define STM32_HAS_TIM10 FALSE +#endif + +#if !defined(STM32_HAS_TIM11) +#define STM32_HAS_TIM11 FALSE +#endif + +#if !defined(STM32_HAS_TIM12) +#define STM32_HAS_TIM12 FALSE +#endif + +#if !defined(STM32_HAS_TIM13) +#define STM32_HAS_TIM13 FALSE +#endif + +#if !defined(STM32_HAS_TIM14) +#define STM32_HAS_TIM14 FALSE +#endif + +#if !defined(STM32_HAS_TIM15) +#define STM32_HAS_TIM15 FALSE +#endif + +#if !defined(STM32_HAS_TIM16) +#define STM32_HAS_TIM16 FALSE +#endif + +#if !defined(STM32_HAS_TIM17) +#define STM32_HAS_TIM17 FALSE +#endif + +#if !defined(STM32_HAS_TIM21) +#define STM32_HAS_TIM21 FALSE +#endif + +#if !defined(STM32_HAS_TIM22) +#define STM32_HAS_TIM22 FALSE +#endif + +#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6 +#error "TIM6 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7 +#error "TIM7 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM10 && !STM32_HAS_TIM10 +#error "TIM10 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11 +#error "TIM11 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12 +#error "TIM12 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM13 && !STM32_HAS_TIM13 +#error "TIM13 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14 +#error "TIM14 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM15 && !STM32_HAS_TIM15 +#error "TIM15 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM16 && !STM32_HAS_TIM16 +#error "TIM16 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM17 && !STM32_HAS_TIM17 +#error "TIM17 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM21 && !STM32_HAS_TIM21 +#error "TIM21 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM22 && !STM32_HAS_TIM22 +#error "TIM22 not present in the selected device" +#endif + +#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \ + !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \ + !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \ + !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \ + !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM10 && \ + !STM32_GPT_USE_TIM11 && !STM32_GPT_USE_TIM12 && \ + !STM32_GPT_USE_TIM13 && !STM32_GPT_USE_TIM14 && \ + !STM32_GPT_USE_TIM15 && !STM32_GPT_USE_TIM16 && \ + !STM32_GPT_USE_TIM17 && \ + !STM32_GPT_USE_TIM21 && !STM32_GPT_USE_TIM22 +#error "GPT driver activated but no TIM peripheral assigned" +#endif + +/* Checks on allocation of TIMx units.*/ +#if STM32_GPT_USE_TIM1 +#if defined(STM32_TIM1_IS_USED) +#error "GPTD1 requires TIM1 but the timer is already used" +#else +#define STM32_TIM1_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM2 +#if defined(STM32_TIM2_IS_USED) +#error "GPTD2 requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM3 +#if defined(STM32_TIM3_IS_USED) +#error "GPTD3 requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM4 +#if defined(STM32_TIM4_IS_USED) +#error "GPTD4 requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM5 +#if defined(STM32_TIM5_IS_USED) +#error "GPTD5 requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM6 +#if defined(STM32_TIM6_IS_USED) +#error "GPTD6 requires TIM6 but the timer is already used" +#else +#define STM32_TIM6_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM7 +#if defined(STM32_TIM7_IS_USED) +#error "GPTD7 requires TIM7 but the timer is already used" +#else +#define STM32_TIM7_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM8 +#if defined(STM32_TIM8_IS_USED) +#error "GPTD8 requires TIM8 but the timer is already used" +#else +#define STM32_TIM8_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM9 +#if defined(STM32_TIM9_IS_USED) +#error "GPTD9 requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM10 +#if defined(STM32_TIM10_IS_USED) +#error "GPTD10 requires TIM10 but the timer is already used" +#else +#define STM32_TIM10_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM11 +#if defined(STM32_TIM11_IS_USED) +#error "GPTD11 requires TIM11 but the timer is already used" +#else +#define STM32_TIM11_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM12 +#if defined(STM32_TIM12_IS_USED) +#error "GPTD12 requires TIM12 but the timer is already used" +#else +#define STM32_TIM12_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM13 +#if defined(STM32_TIM13_IS_USED) +#error "GPTD13 requires TIM13 but the timer is already used" +#else +#define STM32_TIM13_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM14 +#if defined(STM32_TIM14_IS_USED) +#error "GPTD14 requires TIM14 but the timer is already used" +#else +#define STM32_TIM14_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM15 +#if defined(STM32_TIM15_IS_USED) +#error "GPTD14 requires TIM15 but the timer is already used" +#else +#define STM32_TIM15_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM16 +#if defined(STM32_TIM16_IS_USED) +#error "GPTD14 requires TIM16 but the timer is already used" +#else +#define STM32_TIM16_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM17 +#if defined(STM32_TIM17_IS_USED) +#error "GPTD14 requires TIM17 but the timer is already used" +#else +#define STM32_TIM17_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM21 +#if defined(STM32_TIM21_IS_USED) +#error "GPTD21 requires TIM21 but the timer is already used" +#else +#define STM32_TIM21_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM22 +#if defined(STM32_TIM22_IS_USED) +#error "GPTD22 requires TIM22 but the timer is already used" +#else +#define STM32_TIM22_IS_USED +#endif +#endif + +/* IRQ priority checks.*/ +#if STM32_GPT_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_GPT_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_GPT_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_GPT_USE_TIM4 && !defined(STM32_TIM_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_GPT_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_GPT_USE_TIM6 && !defined(STM32_TIM6_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM6" +#endif + +#if STM32_GPT_USE_TIM7 && !defined(STM32_TIM7_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM7" +#endif + +#if STM32_GPT_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_GPT_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +#if STM32_GPT_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM10_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM10" +#endif + +#if STM32_GPT_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM11" +#endif + +#if STM32_GPT_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM12" +#endif + +#if STM32_GPT_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM13_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM13" +#endif + +#if STM32_GPT_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM14" +#endif + +#if STM32_GPT_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM15_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM15" +#endif + +#if STM32_GPT_USE_TIM16 && !defined(STM32_TIM16_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM16_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM16" +#endif + +#if STM32_GPT_USE_TIM17 && !defined(STM32_TIM17_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM17_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM17" +#endif + +#if STM32_GPT_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM21_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM21" +#endif + +#if STM32_GPT_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM22_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM22" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief GPT frequency type. + */ +typedef uint32_t gptfreq_t; + +/** + * @brief GPT counter type. + */ +typedef uint32_t gptcnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + gptfreq_t frequency; + /** + * @brief Timer callback pointer. + * @note This callback is invoked on GPT counter events. + * @note This callback can be set to @p NULL but in that case the + * one-shot mode cannot be used. + */ + gptcallback_t callback; + /* End of the mandatory fields.*/ + /** + * @brief TIM CR2 register initialization data. + * @note The value of this field should normally be equal to zero. + */ + uint32_t cr2; + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} GPTConfig; + +/** + * @brief Structure representing a GPT driver. + */ +struct GPTDriver { + /** + * @brief Driver state. + */ + gptstate_t state; + /** + * @brief Current configuration data. + */ + const GPTConfig *config; +#if defined(GPT_DRIVER_EXT_FIELDS) + GPT_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must be running in continuous mode. + * @post The GPT unit interval is changed to the new value. + * @note The function has effect at the next cycle start. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * + * @notapi + */ +#define gpt_lld_change_interval(gptp, interval) \ + ((gptp)->tim->ARR = (uint32_t)((interval) - 1U)) + +/** + * @brief Returns the interval of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current interval. + * + * @notapi + */ +#define gpt_lld_get_interval(gptp) ((gptcnt_t)((gptp)->tim->ARR + 1U)) + +/** + * @brief Returns the counter value of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * @note The nature of the counter is not defined, it may count upward + * or downward, it could be continuously running or not. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current counter value. + * + * @notapi + */ +#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->tim->CNT) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD1; +#endif + +#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__) +extern GPTDriver GPTD2; +#endif + +#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__) +extern GPTDriver GPTD3; +#endif + +#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__) +extern GPTDriver GPTD4; +#endif + +#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__) +extern GPTDriver GPTD5; +#endif + +#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__) +extern GPTDriver GPTD6; +#endif + +#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__) +extern GPTDriver GPTD7; +#endif + +#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__) +extern GPTDriver GPTD8; +#endif + +#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__) +extern GPTDriver GPTD9; +#endif + +#if STM32_GPT_USE_TIM10 && !defined(__DOXYGEN__) +extern GPTDriver GPTD10; +#endif + +#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__) +extern GPTDriver GPTD11; +#endif + +#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__) +extern GPTDriver GPTD12; +#endif + +#if STM32_GPT_USE_TIM13 && !defined(__DOXYGEN__) +extern GPTDriver GPTD13; +#endif + +#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__) +extern GPTDriver GPTD14; +#endif + +#if STM32_GPT_USE_TIM15 && !defined(__DOXYGEN__) +extern GPTDriver GPTD15; +#endif + +#if STM32_GPT_USE_TIM16 && !defined(__DOXYGEN__) +extern GPTDriver GPTD16; +#endif + +#if STM32_GPT_USE_TIM17 && !defined(__DOXYGEN__) +extern GPTDriver GPTD17; +#endif + +#if STM32_GPT_USE_TIM21 && !defined(__DOXYGEN__) +extern GPTDriver GPTD21; +#endif + +#if STM32_GPT_USE_TIM22 && !defined(__DOXYGEN__) +extern GPTDriver GPTD22; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void gpt_lld_init(void); + void gpt_lld_start(GPTDriver *gptp); + void gpt_lld_stop(GPTDriver *gptp); + void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); + void gpt_lld_stop_timer(GPTDriver *gptp); + void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); + void gpt_lld_serve_interrupt(GPTDriver *gptp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* HAL_GPT_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c index e9a669dd66..cd3781a4f5 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c @@ -1,1135 +1,1135 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Fabio Utzig and - Xo Wang. - */ - -/** - * @file TIMv1/hal_icu_lld.c - * @brief STM32 ICU subsystem low level driver header. - * - * @addtogroup ICU - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief ICUD1 driver identifier. - * @note The driver ICUD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) -ICUDriver ICUD1; -#endif - -/** - * @brief ICUD2 driver identifier. - * @note The driver ICUD1 allocates the timer TIM2 when enabled. - */ -#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) -ICUDriver ICUD2; -#endif - -/** - * @brief ICUD3 driver identifier. - * @note The driver ICUD1 allocates the timer TIM3 when enabled. - */ -#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) -ICUDriver ICUD3; -#endif - -/** - * @brief ICUD4 driver identifier. - * @note The driver ICUD4 allocates the timer TIM4 when enabled. - */ -#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) -ICUDriver ICUD4; -#endif - -/** - * @brief ICUD5 driver identifier. - * @note The driver ICUD5 allocates the timer TIM5 when enabled. - */ -#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) -ICUDriver ICUD5; -#endif - -/** - * @brief ICUD8 driver identifier. - * @note The driver ICUD8 allocates the timer TIM8 when enabled. - */ -#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) -ICUDriver ICUD8; -#endif - -/** - * @brief ICUD9 driver identifier. - * @note The driver ICUD9 allocates the timer TIM9 when enabled. - */ -#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) -ICUDriver ICUD9; -#endif - -/** - * @brief ICUD10 driver identifier. - * @note The driver ICUD10 allocates the timer TIM10 when enabled. - */ -#if STM32_ICU_USE_TIM10 || defined(__DOXYGEN__) -ICUDriver ICUD10; -#endif - -/** - * @brief ICUD11 driver identifier. - * @note The driver ICUD11 allocates the timer TIM11 when enabled. - */ -#if STM32_ICU_USE_TIM11 || defined(__DOXYGEN__) -ICUDriver ICUD11; -#endif - -/** - * @brief ICUD12 driver identifier. - * @note The driver ICUD12 allocates the timer TIM12 when enabled. - */ -#if STM32_ICU_USE_TIM12 || defined(__DOXYGEN__) -ICUDriver ICUD12; -#endif - -/** - * @brief ICUD13 driver identifier. - * @note The driver ICUD13 allocates the timer TIM13 when enabled. - */ -#if STM32_ICU_USE_TIM13 || defined(__DOXYGEN__) -ICUDriver ICUD13; -#endif - -/** - * @brief ICUD14 driver identifier. - * @note The driver ICUD14 allocates the timer TIM14 when enabled. - */ -#if STM32_ICU_USE_TIM14 || defined(__DOXYGEN__) -ICUDriver ICUD14; -#endif - -/** - * @brief ICUD15 driver identifier. - * @note The driver ICUD15 allocates the timer TIM15 when enabled. - */ -#if STM32_ICU_USE_TIM15 || defined(__DOXYGEN__) -ICUDriver ICUD15; -#endif - -/** - * @brief ICUD20 driver identifier. - * @note The driver ICUD20 allocates the timer TIM20 when enabled. - */ -#if STM32_ICU_USE_TIM20 || defined(__DOXYGEN__) -ICUDriver ICUD20; -#endif - -/** - * @brief ICUD21 driver identifier. - * @note The driver ICUD21 allocates the timer TIM21 when enabled. - */ -#if STM32_ICU_USE_TIM21 || defined(__DOXYGEN__) -ICUDriver ICUD21; -#endif - -/** - * @brief ICUD22 driver identifier. - * @note The driver ICUD22 allocates the timer TIM22 when enabled. - */ -#if STM32_ICU_USE_TIM22 || defined(__DOXYGEN__) -ICUDriver ICUD22; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static bool icu_lld_wait_edge(ICUDriver *icup) { - uint32_t sr; - bool result; - - /* Polled mode so re-enabling the interrupts while the operation is - performed.*/ - osalSysUnlock(); - - /* Polling the right bit depending on the input channel.*/ - if (icup->config->channel == ICU_CHANNEL_1) { - /* Waiting for an edge.*/ - while (((sr = icup->tim->SR) & - (STM32_TIM_SR_CC1IF | STM32_TIM_SR_UIF)) == 0) - ; - } - else { - /* Waiting for an edge.*/ - while (((sr = icup->tim->SR) & - (STM32_TIM_SR_CC2IF | STM32_TIM_SR_UIF)) == 0) - ; - } - - /* Edge or overflow?*/ - result = (sr & STM32_TIM_SR_UIF) != 0 ? true : false; - - /* Done, disabling interrupts again.*/ - osalSysLock(); - - /* Resetting all flags.*/ - icup->tim->SR &= ~(STM32_TIM_SR_CC1IF | - STM32_TIM_SR_CC2IF | - STM32_TIM_SR_UIF); - - return result; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) -#if !defined(STM32_TIM1_SUPPRESS_ISR) -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM1 */ - -#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) -#if !defined(STM32_TIM2_SUPPRESS_ISR) -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM2 */ - -#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) -#if !defined(STM32_TIM3_SUPPRESS_ISR) -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM3 */ - -#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) -#if !defined(STM32_TIM4_SUPPRESS_ISR) -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM4 */ - -#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) -#if !defined(STM32_TIM5_SUPPRESS_ISR) -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM5 */ - -#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) -#if !defined(STM32_TIM8_SUPPRESS_ISR) -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM8 */ - -#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) -#if !defined(STM32_TIM9_SUPPRESS_ISR) -#error "TIM9 ISR not defined by platform" -#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM9 */ - -#if STM32_ICU_USE_TIM10 || defined(__DOXYGEN__) -#if !defined(STM32_TIM10_SUPPRESS_ISR) -#error "TIM10 ISR not defined by platform" -#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM10 */ - -#if STM32_ICU_USE_TIM11 || defined(__DOXYGEN__) -#if !defined(STM32_TIM11_SUPPRESS_ISR) -#error "TIM11 ISR not defined by platform" -#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM11 */ - -#if STM32_ICU_USE_TIM12 || defined(__DOXYGEN__) -#if !defined(STM32_TIM12_SUPPRESS_ISR) -#error "TIM12 ISR not defined by platform" -#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM12 */ - -#if STM32_ICU_USE_TIM13 || defined(__DOXYGEN__) -#if !defined(STM32_TIM13_SUPPRESS_ISR) -#error "TIM13 ISR not defined by platform" -#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM13 */ - -#if STM32_ICU_USE_TIM14 || defined(__DOXYGEN__) -#if !defined(STM32_TIM14_SUPPRESS_ISR) -#error "TIM14 ISR not defined by platform" -#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM14 */ - -#if STM32_ICU_USE_TIM15 || defined(__DOXYGEN__) -#if !defined(STM32_TIM15_SUPPRESS_ISR) -#error "TIM15 ISR not defined by platform" -#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM15 */ - -#if STM32_ICU_USE_TIM20 || defined(__DOXYGEN__) -#if !defined(STM32_TIM20_SUPPRESS_ISR) -#error "TIM20 ISR not defined by platform" -#endif /* !defined(STM32_TIM20_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM20 */ - -#if STM32_ICU_USE_TIM21 || defined(__DOXYGEN__) -#if !defined(STM32_TIM21_SUPPRESS_ISR) -#error "TIM21 ISR not defined by platform" -#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM21 */ - -#if STM32_ICU_USE_TIM22 || defined(__DOXYGEN__) -#if !defined(STM32_TIM22_SUPPRESS_ISR) -#error "TIM22 ISR not defined by platform" -#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM22 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ICU driver initialization. - * - * @notapi - */ -void icu_lld_init(void) { - -#if STM32_ICU_USE_TIM1 - /* Driver initialization.*/ - icuObjectInit(&ICUD1); - ICUD1.tim = STM32_TIM1; -#endif - -#if STM32_ICU_USE_TIM2 - /* Driver initialization.*/ - icuObjectInit(&ICUD2); - ICUD2.tim = STM32_TIM2; -#endif - -#if STM32_ICU_USE_TIM3 - /* Driver initialization.*/ - icuObjectInit(&ICUD3); - ICUD3.tim = STM32_TIM3; -#endif - -#if STM32_ICU_USE_TIM4 - /* Driver initialization.*/ - icuObjectInit(&ICUD4); - ICUD4.tim = STM32_TIM4; -#endif - -#if STM32_ICU_USE_TIM5 - /* Driver initialization.*/ - icuObjectInit(&ICUD5); - ICUD5.tim = STM32_TIM5; -#endif - -#if STM32_ICU_USE_TIM8 - /* Driver initialization.*/ - icuObjectInit(&ICUD8); - ICUD8.tim = STM32_TIM8; -#endif - -#if STM32_ICU_USE_TIM9 - /* Driver initialization.*/ - icuObjectInit(&ICUD9); - ICUD9.tim = STM32_TIM9; -#endif - -#if STM32_ICU_USE_TIM10 - /* Driver initialization.*/ - icuObjectInit(&ICUD10); - ICUD10.tim = STM32_TIM10; -#endif - -#if STM32_ICU_USE_TIM11 - /* Driver initialization.*/ - icuObjectInit(&ICUD11); - ICUD11.tim = STM32_TIM11; -#endif - -#if STM32_ICU_USE_TIM12 - /* Driver initialization.*/ - icuObjectInit(&ICUD12); - ICUD12.tim = STM32_TIM12; -#endif - -#if STM32_ICU_USE_TIM13 - /* Driver initialization.*/ - icuObjectInit(&ICUD13); - ICUD13.tim = STM32_TIM13; -#endif - -#if STM32_ICU_USE_TIM14 - /* Driver initialization.*/ - icuObjectInit(&ICUD14); - ICUD14.tim = STM32_TIM14; -#endif - -#if STM32_ICU_USE_TIM15 - /* Driver initialization.*/ - icuObjectInit(&ICUD15); - ICUD15.tim = STM32_TIM15; -#endif - -#if STM32_ICU_USE_TIM20 - /* Driver initialization.*/ - icuObjectInit(&ICUD20); - ICUD20.tim = STM32_TIM20; -#endif - -#if STM32_ICU_USE_TIM21 - /* Driver initialization.*/ - icuObjectInit(&ICUD21); - ICUD21.tim = STM32_TIM21; -#endif - -#if STM32_ICU_USE_TIM22 - /* Driver initialization.*/ - icuObjectInit(&ICUD22); - ICUD22.tim = STM32_TIM22; -#endif -} - -/** - * @brief Configures and activates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_start(ICUDriver *icup) { - uint32_t psc; - - osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || - (icup->config->channel == ICU_CHANNEL_2), - "invalid input"); - - if (icup->state == ICU_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { - rccEnableTIM1(true); - rccResetTIM1(); -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM1CLK) - icup->clock = STM32_TIM1CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { - rccEnableTIM2(true); - rccResetTIM2(); -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM2CLK) - icup->clock = STM32_TIM2CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { - rccEnableTIM3(true); - rccResetTIM3(); -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM3CLK) - icup->clock = STM32_TIM3CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { - rccEnableTIM4(true); - rccResetTIM4(); -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM4CLK) - icup->clock = STM32_TIM4CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { - rccEnableTIM5(true); - rccResetTIM5(); -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM5CLK) - icup->clock = STM32_TIM5CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { - rccEnableTIM8(true); - rccResetTIM8(); -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM8CLK) - icup->clock = STM32_TIM8CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - rccEnableTIM9(true); - rccResetTIM9(); -#if defined(STM32_TIM9CLK) - icup->clock = STM32_TIM9CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM10 - if (&ICUD10 == icup) { - rccEnableTIM10(true); - rccResetTIM10(); -#if defined(STM32_TIM10CLK) - icup->clock = STM32_TIM10CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM11 - if (&ICUD11 == icup) { - rccEnableTIM11(true); - rccResetTIM11(); -#if defined(STM32_TIM11CLK) - icup->clock = STM32_TIM11CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM12 - if (&ICUD12 == icup) { - rccEnableTIM12(true); - rccResetTIM12(); -#if defined(STM32_TIM12CLK) - icup->clock = STM32_TIM12CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM13 - if (&ICUD13 == icup) { - rccEnableTIM13(true); - rccResetTIM13(); -#if defined(STM32_TIM13CLK) - icup->clock = STM32_TIM13CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM14 - if (&ICUD14 == icup) { - rccEnableTIM14(true); - rccResetTIM14(); -#if defined(STM32_TIM14CLK) - icup->clock = STM32_TIM14CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM15 - if (&ICUD15 == icup) { - rccEnableTIM15(true); - rccResetTIM15(); -#if defined(STM32_TIM15CLK) - icup->clock = STM32_TIM15CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM20 - if (&ICUD20 == icup) { - rccEnableTIM20(true); - rccResetTIM20(); -#if defined(STM32_TIM20CLK) - icup->clock = STM32_TIM20CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM21 - if (&ICUD21 == icup) { - rccEnableTIM21(true); - rccResetTIM21(); -#if defined(STM32_TIM21CLK) - icup->clock = STM32_TIM21CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM22 - if (&ICUD22 == icup) { - rccEnableTIM22(true); - rccResetTIM22(); -#if defined(STM32_TIM22CLK) - icup->clock = STM32_TIM22CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ - icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ - icup->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - icup->tim->DIER = icup->config->dier & /* DMA-related DIER settings. */ - ~STM32_TIM_DIER_IRQ_MASK; - psc = (icup->clock / icup->config->frequency) - 1; - osalDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * icup->config->frequency) == icup->clock, - "invalid frequency"); - icup->tim->PSC = psc; - if (icup->config->arr == 0U) { - /* Zero is an invalid value and is turned in maximum value, also for - legacy configurations compatibility.*/ - icup->tim->ARR = 0xFFFFFFFFU; - } - else { - icup->tim->ARR = icup->config->arr; - } - - if (icup->config->channel == ICU_CHANNEL_1) { - /* Selected input 1. - CCMR1_CC1S = 01 = CH1 Input on TI1. - CCMR1_CC2S = 10 = CH2 Input on TI1.*/ - icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); - - /* SMCR_TS = 101, input is TI1FP1. - SMCR_SMS = 100, reset on rising edge.*/ - icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); - - /* The CCER settings depend on the selected trigger mode. - ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. - ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ - if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) - icup->tim->CCER = STM32_TIM_CCER_CC1E | - STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; - else - icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | - STM32_TIM_CCER_CC2E; - - /* Direct pointers to the capture registers in order to make reading - data faster from within callbacks.*/ - icup->wccrp = &icup->tim->CCR[1]; - icup->pccrp = &icup->tim->CCR[0]; - } - else { - /* Selected input 2. - CCMR1_CC1S = 10 = CH1 Input on TI2. - CCMR1_CC2S = 01 = CH2 Input on TI2.*/ - icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); - - /* SMCR_TS = 110, input is TI2FP2. - SMCR_SMS = 100, reset on rising edge.*/ - icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); - - /* The CCER settings depend on the selected trigger mode. - ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. - ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ - if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) - icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | - STM32_TIM_CCER_CC2E; - else - icup->tim->CCER = STM32_TIM_CCER_CC1E | - STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; - - /* Direct pointers to the capture registers in order to make reading - data faster from within callbacks.*/ - icup->wccrp = &icup->tim->CCR[0]; - icup->pccrp = &icup->tim->CCR[1]; - } -} - -/** - * @brief Deactivates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_stop(ICUDriver *icup) { - - if (icup->state == ICU_READY) { - /* Clock deactivation.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - icup->tim->DIER = 0; /* All IRQs disabled. */ - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); -#endif - rccDisableTIM1(); - } -#endif - -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM2_NUMBER); -#endif - rccDisableTIM2(); - } -#endif - -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM3_NUMBER); -#endif - rccDisableTIM3(); - } -#endif - -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM4_NUMBER); -#endif - rccDisableTIM4(); - } -#endif - -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM5_NUMBER); -#endif - rccDisableTIM5(); - } -#endif - -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); -#endif - rccDisableTIM8(); - } -#endif - -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - rccDisableTIM9(); - } -#endif - -#if STM32_ICU_USE_TIM10 - if (&ICUD10 == icup) { - rccDisableTIM10(); - } -#endif - -#if STM32_ICU_USE_TIM11 - if (&ICUD11 == icup) { - rccDisableTIM11(); - } -#endif - -#if STM32_ICU_USE_TIM12 - if (&ICUD12 == icup) { - rccDisableTIM12(); - } -#endif - -#if STM32_ICU_USE_TIM13 - if (&ICUD13 == icup) { - rccDisableTIM13(); - } -#endif - -#if STM32_ICU_USE_TIM14 - if (&ICUD14 == icup) { - rccDisableTIM14(); - } -#endif - -#if STM32_ICU_USE_TIM15 - if (&ICUD15 == icup) { - rccDisableTIM15(); - } -#endif - -#if STM32_ICU_USE_TIM20 - if (&ICUD20 == icup) { - rccDisableTIM20(); - } -#endif - -#if STM32_ICU_USE_TIM21 - if (&ICUD21 == icup) { - rccDisableTIM21(); - } -#endif - -#if STM32_ICU_USE_TIM22 - if (&ICUD22 == icup) { - rccDisableTIM22(); - } -#endif - } -} - -/** - * @brief Starts the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_start_capture(ICUDriver *icup) { - - /* Triggering an UG and clearing the IRQ status.*/ - icup->tim->EGR |= STM32_TIM_EGR_UG; - icup->tim->SR = 0; - - /* Timer is started.*/ - icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Waits for a completed capture. - * @note The operation is performed in polled mode. - * @note In order to use this function notifications must be disabled. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The capture status. - * @retval false if the capture is successful. - * @retval true if a timer overflow occurred. - * - * @notapi - */ -bool icu_lld_wait_capture(ICUDriver *icup) { - - /* If the driver is still in the ICU_WAITING state then we need to wait - for the first activation edge.*/ - if (icup->state == ICU_WAITING) - if (icu_lld_wait_edge(icup)) - return true; - - /* This edge marks the availability of a capture result.*/ - return icu_lld_wait_edge(icup); -} - -/** - * @brief Stops the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_stop_capture(ICUDriver *icup) { - - /* Timer stopped.*/ - icup->tim->CR1 = 0; - - /* All interrupts disabled.*/ - icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Enables notifications. - * @pre The ICU unit must have been activated using @p icuStart() and the - * capture started using @p icuStartCapture(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_enable_notifications(ICUDriver *icup) { - uint32_t dier = icup->tim->DIER; - - /* If interrupts were already enabled then the operation is skipped. - This is done in order to avoid clearing the SR and risk losing - pending interrupts.*/ - if ((dier & STM32_TIM_DIER_IRQ_MASK) == 0) { - /* Previously triggered IRQs are ignored, status cleared.*/ - icup->tim->SR = 0; - - if (icup->config->channel == ICU_CHANNEL_1) { - /* Enabling periodic callback on CC1.*/ - dier |= STM32_TIM_DIER_CC1IE; - - /* Optionally enabling width callback on CC2.*/ - if (icup->config->width_cb != NULL) - dier |= STM32_TIM_DIER_CC2IE; - } - else { - /* Enabling periodic callback on CC2.*/ - dier |= STM32_TIM_DIER_CC2IE; - - /* Optionally enabling width callback on CC1.*/ - if (icup->config->width_cb != NULL) - dier |= STM32_TIM_DIER_CC1IE; - } - - /* If an overflow callback is defined then also the overflow callback - is enabled.*/ - if (icup->config->overflow_cb != NULL) - dier |= STM32_TIM_DIER_UIE; - - /* One single atomic write.*/ - icup->tim->DIER = dier; - } -} - -/** - * @brief Disables notifications. - * @pre The ICU unit must have been activated using @p icuStart() and the - * capture started using @p icuStartCapture(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_disable_notifications(ICUDriver *icup) { - - /* All interrupts disabled.*/ - icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Shared IRQ handler. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_serve_interrupt(ICUDriver *icup) { - uint32_t sr; - - sr = icup->tim->SR; - sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - icup->tim->SR = ~sr; - if (icup->config->channel == ICU_CHANNEL_1) { - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_width_cb(icup); - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_period_cb(icup); - } - else { - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_width_cb(icup); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_period_cb(icup); - } - if ((sr & STM32_TIM_SR_UIF) != 0) - _icu_isr_invoke_overflow_cb(icup); -} - -#endif /* HAL_USE_ICU */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Fabio Utzig and + Xo Wang. + */ + +/** + * @file TIMv1/hal_icu_lld.c + * @brief STM32 ICU subsystem low level driver header. + * + * @addtogroup ICU + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief ICUD1 driver identifier. + * @note The driver ICUD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) +ICUDriver ICUD1; +#endif + +/** + * @brief ICUD2 driver identifier. + * @note The driver ICUD1 allocates the timer TIM2 when enabled. + */ +#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) +ICUDriver ICUD2; +#endif + +/** + * @brief ICUD3 driver identifier. + * @note The driver ICUD1 allocates the timer TIM3 when enabled. + */ +#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) +ICUDriver ICUD3; +#endif + +/** + * @brief ICUD4 driver identifier. + * @note The driver ICUD4 allocates the timer TIM4 when enabled. + */ +#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) +ICUDriver ICUD4; +#endif + +/** + * @brief ICUD5 driver identifier. + * @note The driver ICUD5 allocates the timer TIM5 when enabled. + */ +#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) +ICUDriver ICUD5; +#endif + +/** + * @brief ICUD8 driver identifier. + * @note The driver ICUD8 allocates the timer TIM8 when enabled. + */ +#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) +ICUDriver ICUD8; +#endif + +/** + * @brief ICUD9 driver identifier. + * @note The driver ICUD9 allocates the timer TIM9 when enabled. + */ +#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) +ICUDriver ICUD9; +#endif + +/** + * @brief ICUD10 driver identifier. + * @note The driver ICUD10 allocates the timer TIM10 when enabled. + */ +#if STM32_ICU_USE_TIM10 || defined(__DOXYGEN__) +ICUDriver ICUD10; +#endif + +/** + * @brief ICUD11 driver identifier. + * @note The driver ICUD11 allocates the timer TIM11 when enabled. + */ +#if STM32_ICU_USE_TIM11 || defined(__DOXYGEN__) +ICUDriver ICUD11; +#endif + +/** + * @brief ICUD12 driver identifier. + * @note The driver ICUD12 allocates the timer TIM12 when enabled. + */ +#if STM32_ICU_USE_TIM12 || defined(__DOXYGEN__) +ICUDriver ICUD12; +#endif + +/** + * @brief ICUD13 driver identifier. + * @note The driver ICUD13 allocates the timer TIM13 when enabled. + */ +#if STM32_ICU_USE_TIM13 || defined(__DOXYGEN__) +ICUDriver ICUD13; +#endif + +/** + * @brief ICUD14 driver identifier. + * @note The driver ICUD14 allocates the timer TIM14 when enabled. + */ +#if STM32_ICU_USE_TIM14 || defined(__DOXYGEN__) +ICUDriver ICUD14; +#endif + +/** + * @brief ICUD15 driver identifier. + * @note The driver ICUD15 allocates the timer TIM15 when enabled. + */ +#if STM32_ICU_USE_TIM15 || defined(__DOXYGEN__) +ICUDriver ICUD15; +#endif + +/** + * @brief ICUD20 driver identifier. + * @note The driver ICUD20 allocates the timer TIM20 when enabled. + */ +#if STM32_ICU_USE_TIM20 || defined(__DOXYGEN__) +ICUDriver ICUD20; +#endif + +/** + * @brief ICUD21 driver identifier. + * @note The driver ICUD21 allocates the timer TIM21 when enabled. + */ +#if STM32_ICU_USE_TIM21 || defined(__DOXYGEN__) +ICUDriver ICUD21; +#endif + +/** + * @brief ICUD22 driver identifier. + * @note The driver ICUD22 allocates the timer TIM22 when enabled. + */ +#if STM32_ICU_USE_TIM22 || defined(__DOXYGEN__) +ICUDriver ICUD22; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static bool icu_lld_wait_edge(ICUDriver *icup) { + uint32_t sr; + bool result; + + /* Polled mode so re-enabling the interrupts while the operation is + performed.*/ + osalSysUnlock(); + + /* Polling the right bit depending on the input channel.*/ + if (icup->config->channel == ICU_CHANNEL_1) { + /* Waiting for an edge.*/ + while (((sr = icup->tim->SR) & + (STM32_TIM_SR_CC1IF | STM32_TIM_SR_UIF)) == 0) + ; + } + else { + /* Waiting for an edge.*/ + while (((sr = icup->tim->SR) & + (STM32_TIM_SR_CC2IF | STM32_TIM_SR_UIF)) == 0) + ; + } + + /* Edge or overflow?*/ + result = (sr & STM32_TIM_SR_UIF) != 0 ? true : false; + + /* Done, disabling interrupts again.*/ + osalSysLock(); + + /* Resetting all flags.*/ + icup->tim->SR &= ~(STM32_TIM_SR_CC1IF | + STM32_TIM_SR_CC2IF | + STM32_TIM_SR_UIF); + + return result; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) +#if !defined(STM32_TIM1_SUPPRESS_ISR) +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM1 */ + +#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) +#if !defined(STM32_TIM2_SUPPRESS_ISR) +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM2 */ + +#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) +#if !defined(STM32_TIM3_SUPPRESS_ISR) +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM3 */ + +#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) +#if !defined(STM32_TIM4_SUPPRESS_ISR) +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM4 */ + +#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) +#if !defined(STM32_TIM5_SUPPRESS_ISR) +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM5 */ + +#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) +#if !defined(STM32_TIM8_SUPPRESS_ISR) +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM8 */ + +#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) +#if !defined(STM32_TIM9_SUPPRESS_ISR) +#error "TIM9 ISR not defined by platform" +#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM9 */ + +#if STM32_ICU_USE_TIM10 || defined(__DOXYGEN__) +#if !defined(STM32_TIM10_SUPPRESS_ISR) +#error "TIM10 ISR not defined by platform" +#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM10 */ + +#if STM32_ICU_USE_TIM11 || defined(__DOXYGEN__) +#if !defined(STM32_TIM11_SUPPRESS_ISR) +#error "TIM11 ISR not defined by platform" +#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM11 */ + +#if STM32_ICU_USE_TIM12 || defined(__DOXYGEN__) +#if !defined(STM32_TIM12_SUPPRESS_ISR) +#error "TIM12 ISR not defined by platform" +#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM12 */ + +#if STM32_ICU_USE_TIM13 || defined(__DOXYGEN__) +#if !defined(STM32_TIM13_SUPPRESS_ISR) +#error "TIM13 ISR not defined by platform" +#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM13 */ + +#if STM32_ICU_USE_TIM14 || defined(__DOXYGEN__) +#if !defined(STM32_TIM14_SUPPRESS_ISR) +#error "TIM14 ISR not defined by platform" +#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM14 */ + +#if STM32_ICU_USE_TIM15 || defined(__DOXYGEN__) +#if !defined(STM32_TIM15_SUPPRESS_ISR) +#error "TIM15 ISR not defined by platform" +#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM15 */ + +#if STM32_ICU_USE_TIM20 || defined(__DOXYGEN__) +#if !defined(STM32_TIM20_SUPPRESS_ISR) +#error "TIM20 ISR not defined by platform" +#endif /* !defined(STM32_TIM20_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM20 */ + +#if STM32_ICU_USE_TIM21 || defined(__DOXYGEN__) +#if !defined(STM32_TIM21_SUPPRESS_ISR) +#error "TIM21 ISR not defined by platform" +#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM21 */ + +#if STM32_ICU_USE_TIM22 || defined(__DOXYGEN__) +#if !defined(STM32_TIM22_SUPPRESS_ISR) +#error "TIM22 ISR not defined by platform" +#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM22 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ICU driver initialization. + * + * @notapi + */ +void icu_lld_init(void) { + +#if STM32_ICU_USE_TIM1 + /* Driver initialization.*/ + icuObjectInit(&ICUD1); + ICUD1.tim = STM32_TIM1; +#endif + +#if STM32_ICU_USE_TIM2 + /* Driver initialization.*/ + icuObjectInit(&ICUD2); + ICUD2.tim = STM32_TIM2; +#endif + +#if STM32_ICU_USE_TIM3 + /* Driver initialization.*/ + icuObjectInit(&ICUD3); + ICUD3.tim = STM32_TIM3; +#endif + +#if STM32_ICU_USE_TIM4 + /* Driver initialization.*/ + icuObjectInit(&ICUD4); + ICUD4.tim = STM32_TIM4; +#endif + +#if STM32_ICU_USE_TIM5 + /* Driver initialization.*/ + icuObjectInit(&ICUD5); + ICUD5.tim = STM32_TIM5; +#endif + +#if STM32_ICU_USE_TIM8 + /* Driver initialization.*/ + icuObjectInit(&ICUD8); + ICUD8.tim = STM32_TIM8; +#endif + +#if STM32_ICU_USE_TIM9 + /* Driver initialization.*/ + icuObjectInit(&ICUD9); + ICUD9.tim = STM32_TIM9; +#endif + +#if STM32_ICU_USE_TIM10 + /* Driver initialization.*/ + icuObjectInit(&ICUD10); + ICUD10.tim = STM32_TIM10; +#endif + +#if STM32_ICU_USE_TIM11 + /* Driver initialization.*/ + icuObjectInit(&ICUD11); + ICUD11.tim = STM32_TIM11; +#endif + +#if STM32_ICU_USE_TIM12 + /* Driver initialization.*/ + icuObjectInit(&ICUD12); + ICUD12.tim = STM32_TIM12; +#endif + +#if STM32_ICU_USE_TIM13 + /* Driver initialization.*/ + icuObjectInit(&ICUD13); + ICUD13.tim = STM32_TIM13; +#endif + +#if STM32_ICU_USE_TIM14 + /* Driver initialization.*/ + icuObjectInit(&ICUD14); + ICUD14.tim = STM32_TIM14; +#endif + +#if STM32_ICU_USE_TIM15 + /* Driver initialization.*/ + icuObjectInit(&ICUD15); + ICUD15.tim = STM32_TIM15; +#endif + +#if STM32_ICU_USE_TIM20 + /* Driver initialization.*/ + icuObjectInit(&ICUD20); + ICUD20.tim = STM32_TIM20; +#endif + +#if STM32_ICU_USE_TIM21 + /* Driver initialization.*/ + icuObjectInit(&ICUD21); + ICUD21.tim = STM32_TIM21; +#endif + +#if STM32_ICU_USE_TIM22 + /* Driver initialization.*/ + icuObjectInit(&ICUD22); + ICUD22.tim = STM32_TIM22; +#endif +} + +/** + * @brief Configures and activates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_start(ICUDriver *icup) { + uint32_t psc; + + osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || + (icup->config->channel == ICU_CHANNEL_2), + "invalid input"); + + if (icup->state == ICU_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { + rccEnableTIM1(true); + rccResetTIM1(); +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM1CLK) + icup->clock = STM32_TIM1CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { + rccEnableTIM2(true); + rccResetTIM2(); +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM2CLK) + icup->clock = STM32_TIM2CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { + rccEnableTIM3(true); + rccResetTIM3(); +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM3CLK) + icup->clock = STM32_TIM3CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { + rccEnableTIM4(true); + rccResetTIM4(); +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM4CLK) + icup->clock = STM32_TIM4CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { + rccEnableTIM5(true); + rccResetTIM5(); +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM5CLK) + icup->clock = STM32_TIM5CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { + rccEnableTIM8(true); + rccResetTIM8(); +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM8CLK) + icup->clock = STM32_TIM8CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + rccEnableTIM9(true); + rccResetTIM9(); +#if defined(STM32_TIM9CLK) + icup->clock = STM32_TIM9CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM10 + if (&ICUD10 == icup) { + rccEnableTIM10(true); + rccResetTIM10(); +#if defined(STM32_TIM10CLK) + icup->clock = STM32_TIM10CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM11 + if (&ICUD11 == icup) { + rccEnableTIM11(true); + rccResetTIM11(); +#if defined(STM32_TIM11CLK) + icup->clock = STM32_TIM11CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM12 + if (&ICUD12 == icup) { + rccEnableTIM12(true); + rccResetTIM12(); +#if defined(STM32_TIM12CLK) + icup->clock = STM32_TIM12CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM13 + if (&ICUD13 == icup) { + rccEnableTIM13(true); + rccResetTIM13(); +#if defined(STM32_TIM13CLK) + icup->clock = STM32_TIM13CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM14 + if (&ICUD14 == icup) { + rccEnableTIM14(true); + rccResetTIM14(); +#if defined(STM32_TIM14CLK) + icup->clock = STM32_TIM14CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM15 + if (&ICUD15 == icup) { + rccEnableTIM15(true); + rccResetTIM15(); +#if defined(STM32_TIM15CLK) + icup->clock = STM32_TIM15CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM20 + if (&ICUD20 == icup) { + rccEnableTIM20(true); + rccResetTIM20(); +#if defined(STM32_TIM20CLK) + icup->clock = STM32_TIM20CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM21 + if (&ICUD21 == icup) { + rccEnableTIM21(true); + rccResetTIM21(); +#if defined(STM32_TIM21CLK) + icup->clock = STM32_TIM21CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM22 + if (&ICUD22 == icup) { + rccEnableTIM22(true); + rccResetTIM22(); +#if defined(STM32_TIM22CLK) + icup->clock = STM32_TIM22CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ + icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ + icup->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + icup->tim->DIER = icup->config->dier & /* DMA-related DIER settings. */ + ~STM32_TIM_DIER_IRQ_MASK; + psc = (icup->clock / icup->config->frequency) - 1; + osalDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * icup->config->frequency) == icup->clock, + "invalid frequency"); + icup->tim->PSC = psc; + if (icup->config->arr == 0U) { + /* Zero is an invalid value and is turned in maximum value, also for + legacy configurations compatibility.*/ + icup->tim->ARR = 0xFFFFFFFFU; + } + else { + icup->tim->ARR = icup->config->arr; + } + + if (icup->config->channel == ICU_CHANNEL_1) { + /* Selected input 1. + CCMR1_CC1S = 01 = CH1 Input on TI1. + CCMR1_CC2S = 10 = CH2 Input on TI1.*/ + icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); + + /* SMCR_TS = 101, input is TI1FP1. + SMCR_SMS = 100, reset on rising edge.*/ + icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); + + /* The CCER settings depend on the selected trigger mode. + ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. + ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ + if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) + icup->tim->CCER = STM32_TIM_CCER_CC1E | + STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; + else + icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | + STM32_TIM_CCER_CC2E; + + /* Direct pointers to the capture registers in order to make reading + data faster from within callbacks.*/ + icup->wccrp = &icup->tim->CCR[1]; + icup->pccrp = &icup->tim->CCR[0]; + } + else { + /* Selected input 2. + CCMR1_CC1S = 10 = CH1 Input on TI2. + CCMR1_CC2S = 01 = CH2 Input on TI2.*/ + icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); + + /* SMCR_TS = 110, input is TI2FP2. + SMCR_SMS = 100, reset on rising edge.*/ + icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); + + /* The CCER settings depend on the selected trigger mode. + ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. + ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ + if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) + icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | + STM32_TIM_CCER_CC2E; + else + icup->tim->CCER = STM32_TIM_CCER_CC1E | + STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; + + /* Direct pointers to the capture registers in order to make reading + data faster from within callbacks.*/ + icup->wccrp = &icup->tim->CCR[0]; + icup->pccrp = &icup->tim->CCR[1]; + } +} + +/** + * @brief Deactivates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_stop(ICUDriver *icup) { + + if (icup->state == ICU_READY) { + /* Clock deactivation.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + icup->tim->DIER = 0; /* All IRQs disabled. */ + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); +#endif + rccDisableTIM1(); + } +#endif + +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM2_NUMBER); +#endif + rccDisableTIM2(); + } +#endif + +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM3_NUMBER); +#endif + rccDisableTIM3(); + } +#endif + +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM4_NUMBER); +#endif + rccDisableTIM4(); + } +#endif + +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM5_NUMBER); +#endif + rccDisableTIM5(); + } +#endif + +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); +#endif + rccDisableTIM8(); + } +#endif + +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + rccDisableTIM9(); + } +#endif + +#if STM32_ICU_USE_TIM10 + if (&ICUD10 == icup) { + rccDisableTIM10(); + } +#endif + +#if STM32_ICU_USE_TIM11 + if (&ICUD11 == icup) { + rccDisableTIM11(); + } +#endif + +#if STM32_ICU_USE_TIM12 + if (&ICUD12 == icup) { + rccDisableTIM12(); + } +#endif + +#if STM32_ICU_USE_TIM13 + if (&ICUD13 == icup) { + rccDisableTIM13(); + } +#endif + +#if STM32_ICU_USE_TIM14 + if (&ICUD14 == icup) { + rccDisableTIM14(); + } +#endif + +#if STM32_ICU_USE_TIM15 + if (&ICUD15 == icup) { + rccDisableTIM15(); + } +#endif + +#if STM32_ICU_USE_TIM20 + if (&ICUD20 == icup) { + rccDisableTIM20(); + } +#endif + +#if STM32_ICU_USE_TIM21 + if (&ICUD21 == icup) { + rccDisableTIM21(); + } +#endif + +#if STM32_ICU_USE_TIM22 + if (&ICUD22 == icup) { + rccDisableTIM22(); + } +#endif + } +} + +/** + * @brief Starts the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_start_capture(ICUDriver *icup) { + + /* Triggering an UG and clearing the IRQ status.*/ + icup->tim->EGR |= STM32_TIM_EGR_UG; + icup->tim->SR = 0; + + /* Timer is started.*/ + icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Waits for a completed capture. + * @note The operation is performed in polled mode. + * @note In order to use this function notifications must be disabled. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The capture status. + * @retval false if the capture is successful. + * @retval true if a timer overflow occurred. + * + * @notapi + */ +bool icu_lld_wait_capture(ICUDriver *icup) { + + /* If the driver is still in the ICU_WAITING state then we need to wait + for the first activation edge.*/ + if (icup->state == ICU_WAITING) + if (icu_lld_wait_edge(icup)) + return true; + + /* This edge marks the availability of a capture result.*/ + return icu_lld_wait_edge(icup); +} + +/** + * @brief Stops the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_stop_capture(ICUDriver *icup) { + + /* Timer stopped.*/ + icup->tim->CR1 = 0; + + /* All interrupts disabled.*/ + icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Enables notifications. + * @pre The ICU unit must have been activated using @p icuStart() and the + * capture started using @p icuStartCapture(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_enable_notifications(ICUDriver *icup) { + uint32_t dier = icup->tim->DIER; + + /* If interrupts were already enabled then the operation is skipped. + This is done in order to avoid clearing the SR and risk losing + pending interrupts.*/ + if ((dier & STM32_TIM_DIER_IRQ_MASK) == 0) { + /* Previously triggered IRQs are ignored, status cleared.*/ + icup->tim->SR = 0; + + if (icup->config->channel == ICU_CHANNEL_1) { + /* Enabling periodic callback on CC1.*/ + dier |= STM32_TIM_DIER_CC1IE; + + /* Optionally enabling width callback on CC2.*/ + if (icup->config->width_cb != NULL) + dier |= STM32_TIM_DIER_CC2IE; + } + else { + /* Enabling periodic callback on CC2.*/ + dier |= STM32_TIM_DIER_CC2IE; + + /* Optionally enabling width callback on CC1.*/ + if (icup->config->width_cb != NULL) + dier |= STM32_TIM_DIER_CC1IE; + } + + /* If an overflow callback is defined then also the overflow callback + is enabled.*/ + if (icup->config->overflow_cb != NULL) + dier |= STM32_TIM_DIER_UIE; + + /* One single atomic write.*/ + icup->tim->DIER = dier; + } +} + +/** + * @brief Disables notifications. + * @pre The ICU unit must have been activated using @p icuStart() and the + * capture started using @p icuStartCapture(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_disable_notifications(ICUDriver *icup) { + + /* All interrupts disabled.*/ + icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Shared IRQ handler. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_serve_interrupt(ICUDriver *icup) { + uint32_t sr; + + sr = icup->tim->SR; + sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + icup->tim->SR = ~sr; + if (icup->config->channel == ICU_CHANNEL_1) { + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_width_cb(icup); + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_period_cb(icup); + } + else { + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_width_cb(icup); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_period_cb(icup); + } + if ((sr & STM32_TIM_SR_UIF) != 0) + _icu_isr_invoke_overflow_cb(icup); +} + +#endif /* HAL_USE_ICU */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h index 38c19078d3..f106a69bfa 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h @@ -1,893 +1,893 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_icu_lld.h - * @brief STM32 ICU subsystem low level driver header. - * - * @addtogroup ICU - * @{ - */ - -#ifndef HAL_ICU_LLD_H -#define HAL_ICU_LLD_H - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ICUD1 driver enable switch. - * @details If set to @p TRUE the support for ICUD1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM1 FALSE -#endif - -/** - * @brief ICUD2 driver enable switch. - * @details If set to @p TRUE the support for ICUD2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM2 FALSE -#endif - -/** - * @brief ICUD3 driver enable switch. - * @details If set to @p TRUE the support for ICUD3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM3 FALSE -#endif - -/** - * @brief ICUD4 driver enable switch. - * @details If set to @p TRUE the support for ICUD4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM4 FALSE -#endif - -/** - * @brief ICUD5 driver enable switch. - * @details If set to @p TRUE the support for ICUD5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM5 FALSE -#endif - -/** - * @brief ICUD8 driver enable switch. - * @details If set to @p TRUE the support for ICUD8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM8 FALSE -#endif - -/** - * @brief ICUD9 driver enable switch. - * @details If set to @p TRUE the support for ICUD9 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM9 FALSE -#endif - -/** - * @brief ICUD10 driver enable switch. - * @details If set to @p TRUE the support for ICUD10 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM10) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM10 FALSE -#endif - -/** - * @brief ICUD11 driver enable switch. - * @details If set to @p TRUE the support for ICUD11 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM11) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM11 FALSE -#endif - -/** - * @brief ICUD12 driver enable switch. - * @details If set to @p TRUE the support for ICUD12 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM12) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM12 FALSE -#endif - -/** - * @brief ICUD13 driver enable switch. - * @details If set to @p TRUE the support for ICUD13 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM13) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM13 FALSE -#endif - -/** - * @brief ICUD14 driver enable switch. - * @details If set to @p TRUE the support for ICUD14 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM14) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM14 FALSE -#endif - -/** - * @brief ICUD15 driver enable switch. - * @details If set to @p TRUE the support for ICUD15 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM15) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM15 FALSE -#endif - -/** - * @brief ICUD20 driver enable switch. - * @details If set to @p TRUE the support for ICUD20 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM20) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM20 FALSE -#endif - -/** - * @brief ICUD21 driver enable switch. - * @details If set to @p TRUE the support for ICUD21 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM21) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM21 FALSE -#endif - -/** - * @brief ICUD22 driver enable switch. - * @details If set to @p TRUE the support for ICUD22 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ICU_USE_TIM22) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM22 FALSE -#endif - -/** - * @brief ICUD1 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD2 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD3 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD4 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD5 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD8 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD9 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD10 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM10_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD11 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM11_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD12 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM12_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD13 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM13_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD14 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM14_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD15 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM15_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD20 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM20_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM20_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD21 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM21_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD22 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM22_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_TIM1) -#define STM32_HAS_TIM1 FALSE -#endif - -#if !defined(STM32_HAS_TIM2) -#define STM32_HAS_TIM2 FALSE -#endif - -#if !defined(STM32_HAS_TIM3) -#define STM32_HAS_TIM3 FALSE -#endif - -#if !defined(STM32_HAS_TIM4) -#define STM32_HAS_TIM4 FALSE -#endif - -#if !defined(STM32_HAS_TIM5) -#define STM32_HAS_TIM5 FALSE -#endif - -#if !defined(STM32_HAS_TIM8) -#define STM32_HAS_TIM8 FALSE -#endif - -#if !defined(STM32_HAS_TIM9) -#define STM32_HAS_TIM9 FALSE -#endif - -#if !defined(STM32_HAS_TIM10) -#define STM32_HAS_TIM10 FALSE -#endif - -#if !defined(STM32_HAS_TIM11) -#define STM32_HAS_TIM11 FALSE -#endif - -#if !defined(STM32_HAS_TIM12) -#define STM32_HAS_TIM12 FALSE -#endif - -#if !defined(STM32_HAS_TIM13) -#define STM32_HAS_TIM13 FALSE -#endif - -#if !defined(STM32_HAS_TIM14) -#define STM32_HAS_TIM14 FALSE -#endif - -#if !defined(STM32_HAS_TIM15) -#define STM32_HAS_TIM15 FALSE -#endif - -#if !defined(STM32_HAS_TIM20) -#define STM32_HAS_TIM20 FALSE -#endif - -#if !defined(STM32_HAS_TIM21) -#define STM32_HAS_TIM21 FALSE -#endif - -#if !defined(STM32_HAS_TIM22) -#define STM32_HAS_TIM22 FALSE -#endif - -#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM10 && !STM32_HAS_TIM10 -#error "TIM10 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM11 && !STM32_HAS_TIM11 -#error "TIM11 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM12 && !STM32_HAS_TIM12 -#error "TIM12 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM13 && !STM32_HAS_TIM13 -#error "TIM13 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM14 && !STM32_HAS_TIM14 -#error "TIM14 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM15 && !STM32_HAS_TIM15 -#error "TIM15 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM20 && !STM32_HAS_TIM20 -#error "TIM20 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM21 && !STM32_HAS_TIM21 -#error "TIM21 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM22 && !STM32_HAS_TIM22 -#error "TIM22 not present in the selected device" -#endif - -#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \ - !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \ - !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \ - !STM32_ICU_USE_TIM9 && !STM32_ICU_USE_TIM10 && \ - !STM32_ICU_USE_TIM11 && !STM32_ICU_USE_TIM12 && \ - !STM32_ICU_USE_TIM13 && !STM32_ICU_USE_TIM14 && \ - !STM32_ICU_USE_TIM15 && !STM32_ICU_USE_TIM20 && \ - !STM32_ICU_USE_TIM21 && !STM32_ICU_USE_TIM22 -#error "ICU driver activated but no TIM peripheral assigned" -#endif - -/* Checks on allocation of TIMx units.*/ -#if STM32_ICU_USE_TIM1 -#if defined(STM32_TIM1_IS_USED) -#error "ICUD1 requires TIM1 but the timer is already used" -#else -#define STM32_TIM1_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM2 -#if defined(STM32_TIM2_IS_USED) -#error "ICUD2 requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM3 -#if defined(STM32_TIM3_IS_USED) -#error "ICUD3 requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM4 -#if defined(STM32_TIM4_IS_USED) -#error "ICUD4 requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM5 -#if defined(STM32_TIM5_IS_USED) -#error "ICUD5 requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM8 -#if defined(STM32_TIM8_IS_USED) -#error "ICUD8 requires TIM8 but the timer is already used" -#else -#define STM32_TIM8_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM9 -#if defined(STM32_TIM9_IS_USED) -#error "ICUD9 requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM10 -#if defined(STM32_TIM10_IS_USED) -#error "ICUD10 requires TIM10 but the timer is already used" -#else -#define STM32_TIM10_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM11 -#if defined(STM32_TIM11_IS_USED) -#error "ICUD11 requires TIM11 but the timer is already used" -#else -#define STM32_TIM11_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM12 -#if defined(STM32_TIM12_IS_USED) -#error "ICUD12 requires TIM12 but the timer is already used" -#else -#define STM32_TIM12_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM13 -#if defined(STM32_TIM13_IS_USED) -#error "ICUD13 requires TIM13 but the timer is already used" -#else -#define STM32_TIM13_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM14 -#if defined(STM32_TIM14_IS_USED) -#error "ICUD14 requires TIM14 but the timer is already used" -#else -#define STM32_TIM14_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM15 -#if defined(STM32_TIM15_IS_USED) -#error "ICUD15 requires TIM15 but the timer is already used" -#else -#define STM32_TIM15_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM20 -#if defined(STM32_TIM20_IS_USED) -#error "ICUD20 requires TIM20 but the timer is already used" -#else -#define STM32_TIM20_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM21 -#if defined(STM32_TIM21_IS_USED) -#error "ICUD21 requires TIM21 but the timer is already used" -#else -#define STM32_TIM21_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM22 -#if defined(STM32_TIM22_IS_USED) -#error "ICUD22 requires TIM22 but the timer is already used" -#else -#define STM32_TIM22_IS_USED -#endif -#endif - -/* IRQ priority checks.*/ -#if STM32_ICU_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_ICU_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_ICU_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_ICU_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_ICU_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_ICU_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_ICU_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -#if STM32_ICU_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM10_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM10" -#endif - -#if STM32_ICU_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM11_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM11" -#endif - -#if STM32_ICU_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM12" -#endif - -#if STM32_ICU_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM13_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM13" -#endif - -#if STM32_ICU_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM14_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM14" -#endif - -#if STM32_ICU_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM15_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM15" -#endif - -#if STM32_ICU_USE_TIM20 && !defined(STM32_TIM20_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM20_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM20" -#endif - -#if STM32_ICU_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM21_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM21" -#endif - -#if STM32_ICU_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM22_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM22" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ICU driver mode. - */ -typedef enum { - ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */ - ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */ -} icumode_t; - -/** - * @brief ICU frequency type. - */ -typedef uint32_t icufreq_t; - -/** - * @brief ICU channel type. - */ -typedef enum { - ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */ - ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */ -} icuchannel_t; - -/** - * @brief ICU counter type. - */ -typedef uint32_t icucnt_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Driver mode. - */ - icumode_t mode; - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - icufreq_t frequency; - /** - * @brief Callback for pulse width measurement. - */ - icucallback_t width_cb; - /** - * @brief Callback for cycle period measurement. - */ - icucallback_t period_cb; - /** - * @brief Callback for timer overflow. - */ - icucallback_t overflow_cb; - /* End of the mandatory fields.*/ - /** - * @brief Timer input channel to be used. - * @note Only inputs TIMx 1 and 2 are supported. - */ - icuchannel_t channel; - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; - /** - * @brief TIM ARR register initialization data. - * @note The value of this field should normally be equal to 0xFFFFFFFFU. - */ - uint32_t arr; -} ICUConfig; - -/** - * @brief Structure representing an ICU driver. - */ -struct ICUDriver { - /** - * @brief Driver state. - */ - icustate_t state; - /** - * @brief Current configuration data. - */ - const ICUConfig *config; -#if defined(ICU_DRIVER_EXT_FIELDS) - ICU_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; - /** - * @brief CCR register used for width capture. - */ - volatile uint32_t *wccrp; - /** - * @brief CCR register used for period capture. - */ - volatile uint32_t *pccrp; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the width of the latest pulse. - * @details The pulse width is defined as number of ticks between the start - * edge and the stop edge. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @notapi - */ -#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1) - -/** - * @brief Returns the width of the latest cycle. - * @details The cycle width is defined as number of ticks between a start - * edge and the next start edge. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @notapi - */ -#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1) - -/** - * @brief Check on notifications status. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The notifications status. - * @retval false if notifications are not enabled. - * @retval true if notifications are enabled. - * - * @notapi - */ -#define icu_lld_are_notifications_enabled(icup) \ - (bool)(((icup)->tim->DIER & STM32_TIM_DIER_IRQ_MASK) != 0) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__) -extern ICUDriver ICUD1; -#endif - -#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__) -extern ICUDriver ICUD2; -#endif - -#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__) -extern ICUDriver ICUD3; -#endif - -#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__) -extern ICUDriver ICUD4; -#endif - -#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__) -extern ICUDriver ICUD5; -#endif - -#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__) -extern ICUDriver ICUD8; -#endif - -#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__) -extern ICUDriver ICUD9; -#endif - -#if STM32_ICU_USE_TIM10 && !defined(__DOXYGEN__) -extern ICUDriver ICUD10; -#endif - -#if STM32_ICU_USE_TIM11 && !defined(__DOXYGEN__) -extern ICUDriver ICUD11; -#endif - -#if STM32_ICU_USE_TIM12 && !defined(__DOXYGEN__) -extern ICUDriver ICUD12; -#endif - -#if STM32_ICU_USE_TIM13 && !defined(__DOXYGEN__) -extern ICUDriver ICUD13; -#endif - -#if STM32_ICU_USE_TIM14 && !defined(__DOXYGEN__) -extern ICUDriver ICUD14; -#endif - -#if STM32_ICU_USE_TIM15 && !defined(__DOXYGEN__) -extern ICUDriver ICUD15; -#endif - -#if STM32_ICU_USE_TIM20 && !defined(__DOXYGEN__) -extern ICUDriver ICUD20; -#endif - -#if STM32_ICU_USE_TIM21 && !defined(__DOXYGEN__) -extern ICUDriver ICUD21; -#endif - -#if STM32_ICU_USE_TIM22 && !defined(__DOXYGEN__) -extern ICUDriver ICUD22; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void icu_lld_init(void); - void icu_lld_start(ICUDriver *icup); - void icu_lld_stop(ICUDriver *icup); - void icu_lld_start_capture(ICUDriver *icup); - bool icu_lld_wait_capture(ICUDriver *icup); - void icu_lld_stop_capture(ICUDriver *icup); - void icu_lld_enable_notifications(ICUDriver *icup); - void icu_lld_disable_notifications(ICUDriver *icup); - void icu_lld_serve_interrupt(ICUDriver *icup); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ICU */ - -#endif /* HAL_ICU_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_icu_lld.h + * @brief STM32 ICU subsystem low level driver header. + * + * @addtogroup ICU + * @{ + */ + +#ifndef HAL_ICU_LLD_H +#define HAL_ICU_LLD_H + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ICUD1 driver enable switch. + * @details If set to @p TRUE the support for ICUD1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM1 FALSE +#endif + +/** + * @brief ICUD2 driver enable switch. + * @details If set to @p TRUE the support for ICUD2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM2 FALSE +#endif + +/** + * @brief ICUD3 driver enable switch. + * @details If set to @p TRUE the support for ICUD3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM3 FALSE +#endif + +/** + * @brief ICUD4 driver enable switch. + * @details If set to @p TRUE the support for ICUD4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM4 FALSE +#endif + +/** + * @brief ICUD5 driver enable switch. + * @details If set to @p TRUE the support for ICUD5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM5 FALSE +#endif + +/** + * @brief ICUD8 driver enable switch. + * @details If set to @p TRUE the support for ICUD8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM8 FALSE +#endif + +/** + * @brief ICUD9 driver enable switch. + * @details If set to @p TRUE the support for ICUD9 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM9 FALSE +#endif + +/** + * @brief ICUD10 driver enable switch. + * @details If set to @p TRUE the support for ICUD10 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM10) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM10 FALSE +#endif + +/** + * @brief ICUD11 driver enable switch. + * @details If set to @p TRUE the support for ICUD11 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM11) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM11 FALSE +#endif + +/** + * @brief ICUD12 driver enable switch. + * @details If set to @p TRUE the support for ICUD12 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM12) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM12 FALSE +#endif + +/** + * @brief ICUD13 driver enable switch. + * @details If set to @p TRUE the support for ICUD13 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM13) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM13 FALSE +#endif + +/** + * @brief ICUD14 driver enable switch. + * @details If set to @p TRUE the support for ICUD14 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM14) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM14 FALSE +#endif + +/** + * @brief ICUD15 driver enable switch. + * @details If set to @p TRUE the support for ICUD15 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM15) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM15 FALSE +#endif + +/** + * @brief ICUD20 driver enable switch. + * @details If set to @p TRUE the support for ICUD20 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM20) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM20 FALSE +#endif + +/** + * @brief ICUD21 driver enable switch. + * @details If set to @p TRUE the support for ICUD21 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM21) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM21 FALSE +#endif + +/** + * @brief ICUD22 driver enable switch. + * @details If set to @p TRUE the support for ICUD22 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ICU_USE_TIM22) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM22 FALSE +#endif + +/** + * @brief ICUD1 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD2 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD3 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD4 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD5 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD8 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD9 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD10 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM10_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD11 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM11_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD12 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM12_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD13 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM13_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD14 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM14_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD15 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM15_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD20 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM20_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM20_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD21 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM21_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD22 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM22_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_TIM1) +#define STM32_HAS_TIM1 FALSE +#endif + +#if !defined(STM32_HAS_TIM2) +#define STM32_HAS_TIM2 FALSE +#endif + +#if !defined(STM32_HAS_TIM3) +#define STM32_HAS_TIM3 FALSE +#endif + +#if !defined(STM32_HAS_TIM4) +#define STM32_HAS_TIM4 FALSE +#endif + +#if !defined(STM32_HAS_TIM5) +#define STM32_HAS_TIM5 FALSE +#endif + +#if !defined(STM32_HAS_TIM8) +#define STM32_HAS_TIM8 FALSE +#endif + +#if !defined(STM32_HAS_TIM9) +#define STM32_HAS_TIM9 FALSE +#endif + +#if !defined(STM32_HAS_TIM10) +#define STM32_HAS_TIM10 FALSE +#endif + +#if !defined(STM32_HAS_TIM11) +#define STM32_HAS_TIM11 FALSE +#endif + +#if !defined(STM32_HAS_TIM12) +#define STM32_HAS_TIM12 FALSE +#endif + +#if !defined(STM32_HAS_TIM13) +#define STM32_HAS_TIM13 FALSE +#endif + +#if !defined(STM32_HAS_TIM14) +#define STM32_HAS_TIM14 FALSE +#endif + +#if !defined(STM32_HAS_TIM15) +#define STM32_HAS_TIM15 FALSE +#endif + +#if !defined(STM32_HAS_TIM20) +#define STM32_HAS_TIM20 FALSE +#endif + +#if !defined(STM32_HAS_TIM21) +#define STM32_HAS_TIM21 FALSE +#endif + +#if !defined(STM32_HAS_TIM22) +#define STM32_HAS_TIM22 FALSE +#endif + +#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM10 && !STM32_HAS_TIM10 +#error "TIM10 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM11 && !STM32_HAS_TIM11 +#error "TIM11 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM12 && !STM32_HAS_TIM12 +#error "TIM12 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM13 && !STM32_HAS_TIM13 +#error "TIM13 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM14 && !STM32_HAS_TIM14 +#error "TIM14 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM15 && !STM32_HAS_TIM15 +#error "TIM15 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM20 && !STM32_HAS_TIM20 +#error "TIM20 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM21 && !STM32_HAS_TIM21 +#error "TIM21 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM22 && !STM32_HAS_TIM22 +#error "TIM22 not present in the selected device" +#endif + +#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \ + !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \ + !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \ + !STM32_ICU_USE_TIM9 && !STM32_ICU_USE_TIM10 && \ + !STM32_ICU_USE_TIM11 && !STM32_ICU_USE_TIM12 && \ + !STM32_ICU_USE_TIM13 && !STM32_ICU_USE_TIM14 && \ + !STM32_ICU_USE_TIM15 && !STM32_ICU_USE_TIM20 && \ + !STM32_ICU_USE_TIM21 && !STM32_ICU_USE_TIM22 +#error "ICU driver activated but no TIM peripheral assigned" +#endif + +/* Checks on allocation of TIMx units.*/ +#if STM32_ICU_USE_TIM1 +#if defined(STM32_TIM1_IS_USED) +#error "ICUD1 requires TIM1 but the timer is already used" +#else +#define STM32_TIM1_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM2 +#if defined(STM32_TIM2_IS_USED) +#error "ICUD2 requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM3 +#if defined(STM32_TIM3_IS_USED) +#error "ICUD3 requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM4 +#if defined(STM32_TIM4_IS_USED) +#error "ICUD4 requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM5 +#if defined(STM32_TIM5_IS_USED) +#error "ICUD5 requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM8 +#if defined(STM32_TIM8_IS_USED) +#error "ICUD8 requires TIM8 but the timer is already used" +#else +#define STM32_TIM8_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM9 +#if defined(STM32_TIM9_IS_USED) +#error "ICUD9 requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM10 +#if defined(STM32_TIM10_IS_USED) +#error "ICUD10 requires TIM10 but the timer is already used" +#else +#define STM32_TIM10_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM11 +#if defined(STM32_TIM11_IS_USED) +#error "ICUD11 requires TIM11 but the timer is already used" +#else +#define STM32_TIM11_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM12 +#if defined(STM32_TIM12_IS_USED) +#error "ICUD12 requires TIM12 but the timer is already used" +#else +#define STM32_TIM12_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM13 +#if defined(STM32_TIM13_IS_USED) +#error "ICUD13 requires TIM13 but the timer is already used" +#else +#define STM32_TIM13_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM14 +#if defined(STM32_TIM14_IS_USED) +#error "ICUD14 requires TIM14 but the timer is already used" +#else +#define STM32_TIM14_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM15 +#if defined(STM32_TIM15_IS_USED) +#error "ICUD15 requires TIM15 but the timer is already used" +#else +#define STM32_TIM15_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM20 +#if defined(STM32_TIM20_IS_USED) +#error "ICUD20 requires TIM20 but the timer is already used" +#else +#define STM32_TIM20_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM21 +#if defined(STM32_TIM21_IS_USED) +#error "ICUD21 requires TIM21 but the timer is already used" +#else +#define STM32_TIM21_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM22 +#if defined(STM32_TIM22_IS_USED) +#error "ICUD22 requires TIM22 but the timer is already used" +#else +#define STM32_TIM22_IS_USED +#endif +#endif + +/* IRQ priority checks.*/ +#if STM32_ICU_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_ICU_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_ICU_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_ICU_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_ICU_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_ICU_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_ICU_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +#if STM32_ICU_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM10_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM10" +#endif + +#if STM32_ICU_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM11_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM11" +#endif + +#if STM32_ICU_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM12" +#endif + +#if STM32_ICU_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM13_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM13" +#endif + +#if STM32_ICU_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM14_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM14" +#endif + +#if STM32_ICU_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM15_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM15" +#endif + +#if STM32_ICU_USE_TIM20 && !defined(STM32_TIM20_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM20_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM20" +#endif + +#if STM32_ICU_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM21_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM21" +#endif + +#if STM32_ICU_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM22_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM22" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ICU driver mode. + */ +typedef enum { + ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */ + ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */ +} icumode_t; + +/** + * @brief ICU frequency type. + */ +typedef uint32_t icufreq_t; + +/** + * @brief ICU channel type. + */ +typedef enum { + ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */ + ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */ +} icuchannel_t; + +/** + * @brief ICU counter type. + */ +typedef uint32_t icucnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Driver mode. + */ + icumode_t mode; + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + icufreq_t frequency; + /** + * @brief Callback for pulse width measurement. + */ + icucallback_t width_cb; + /** + * @brief Callback for cycle period measurement. + */ + icucallback_t period_cb; + /** + * @brief Callback for timer overflow. + */ + icucallback_t overflow_cb; + /* End of the mandatory fields.*/ + /** + * @brief Timer input channel to be used. + * @note Only inputs TIMx 1 and 2 are supported. + */ + icuchannel_t channel; + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; + /** + * @brief TIM ARR register initialization data. + * @note The value of this field should normally be equal to 0xFFFFFFFFU. + */ + uint32_t arr; +} ICUConfig; + +/** + * @brief Structure representing an ICU driver. + */ +struct ICUDriver { + /** + * @brief Driver state. + */ + icustate_t state; + /** + * @brief Current configuration data. + */ + const ICUConfig *config; +#if defined(ICU_DRIVER_EXT_FIELDS) + ICU_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; + /** + * @brief CCR register used for width capture. + */ + volatile uint32_t *wccrp; + /** + * @brief CCR register used for period capture. + */ + volatile uint32_t *pccrp; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the width of the latest pulse. + * @details The pulse width is defined as number of ticks between the start + * edge and the stop edge. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @notapi + */ +#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1) + +/** + * @brief Returns the width of the latest cycle. + * @details The cycle width is defined as number of ticks between a start + * edge and the next start edge. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @notapi + */ +#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1) + +/** + * @brief Check on notifications status. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The notifications status. + * @retval false if notifications are not enabled. + * @retval true if notifications are enabled. + * + * @notapi + */ +#define icu_lld_are_notifications_enabled(icup) \ + (bool)(((icup)->tim->DIER & STM32_TIM_DIER_IRQ_MASK) != 0) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__) +extern ICUDriver ICUD1; +#endif + +#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__) +extern ICUDriver ICUD2; +#endif + +#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__) +extern ICUDriver ICUD3; +#endif + +#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__) +extern ICUDriver ICUD4; +#endif + +#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__) +extern ICUDriver ICUD5; +#endif + +#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__) +extern ICUDriver ICUD8; +#endif + +#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__) +extern ICUDriver ICUD9; +#endif + +#if STM32_ICU_USE_TIM10 && !defined(__DOXYGEN__) +extern ICUDriver ICUD10; +#endif + +#if STM32_ICU_USE_TIM11 && !defined(__DOXYGEN__) +extern ICUDriver ICUD11; +#endif + +#if STM32_ICU_USE_TIM12 && !defined(__DOXYGEN__) +extern ICUDriver ICUD12; +#endif + +#if STM32_ICU_USE_TIM13 && !defined(__DOXYGEN__) +extern ICUDriver ICUD13; +#endif + +#if STM32_ICU_USE_TIM14 && !defined(__DOXYGEN__) +extern ICUDriver ICUD14; +#endif + +#if STM32_ICU_USE_TIM15 && !defined(__DOXYGEN__) +extern ICUDriver ICUD15; +#endif + +#if STM32_ICU_USE_TIM20 && !defined(__DOXYGEN__) +extern ICUDriver ICUD20; +#endif + +#if STM32_ICU_USE_TIM21 && !defined(__DOXYGEN__) +extern ICUDriver ICUD21; +#endif + +#if STM32_ICU_USE_TIM22 && !defined(__DOXYGEN__) +extern ICUDriver ICUD22; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void icu_lld_init(void); + void icu_lld_start(ICUDriver *icup); + void icu_lld_stop(ICUDriver *icup); + void icu_lld_start_capture(ICUDriver *icup); + bool icu_lld_wait_capture(ICUDriver *icup); + void icu_lld_stop_capture(ICUDriver *icup); + void icu_lld_enable_notifications(ICUDriver *icup); + void icu_lld_disable_notifications(ICUDriver *icup); + void icu_lld_serve_interrupt(ICUDriver *icup); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ICU */ + +#endif /* HAL_ICU_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c index eb6bebc7e4..ddc0f9b959 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c @@ -1,1302 +1,1302 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_pwm_lld.c - * @brief STM32 PWM subsystem low level driver header. - * - * @addtogroup PWM - * @{ - */ - -#include "hal.h" - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief PWMD1 driver identifier. - * @note The driver PWMD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) -PWMDriver PWMD1; -#endif - -/** - * @brief PWMD2 driver identifier. - * @note The driver PWMD2 allocates the timer TIM2 when enabled. - */ -#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) -PWMDriver PWMD2; -#endif - -/** - * @brief PWMD3 driver identifier. - * @note The driver PWMD3 allocates the timer TIM3 when enabled. - */ -#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) -PWMDriver PWMD3; -#endif - -/** - * @brief PWMD4 driver identifier. - * @note The driver PWMD4 allocates the timer TIM4 when enabled. - */ -#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) -PWMDriver PWMD4; -#endif - -/** - * @brief PWMD5 driver identifier. - * @note The driver PWMD5 allocates the timer TIM5 when enabled. - */ -#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) -PWMDriver PWMD5; -#endif - -/** - * @brief PWMD8 driver identifier. - * @note The driver PWMD8 allocates the timer TIM8 when enabled. - */ -#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) -PWMDriver PWMD8; -#endif - -/** - * @brief PWMD9 driver identifier. - * @note The driver PWMD9 allocates the timer TIM9 when enabled. - */ -#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -PWMDriver PWMD9; -#endif - -/** - * @brief PWMD10 driver identifier. - * @note The driver PWMD10 allocates the timer TIM10 when enabled. - */ -#if STM32_PWM_USE_TIM10 || defined(__DOXYGEN__) -PWMDriver PWMD10; -#endif - -/** - * @brief PWMD11 driver identifier. - * @note The driver PWMD11 allocates the timer TIM11 when enabled. - */ -#if STM32_PWM_USE_TIM11 || defined(__DOXYGEN__) -PWMDriver PWMD11; -#endif - -/** - * @brief PWMD12 driver identifier. - * @note The driver PWMD12 allocates the timer TIM12 when enabled. - */ -#if STM32_PWM_USE_TIM12 || defined(__DOXYGEN__) -PWMDriver PWMD12; -#endif - -/** - * @brief PWMD13 driver identifier. - * @note The driver PWMD13 allocates the timer TIM13 when enabled. - */ -#if STM32_PWM_USE_TIM13 || defined(__DOXYGEN__) -PWMDriver PWMD13; -#endif - -/** - * @brief PWMD14 driver identifier. - * @note The driver PWMD14 allocates the timer TIM14 when enabled. - */ -#if STM32_PWM_USE_TIM14 || defined(__DOXYGEN__) -PWMDriver PWMD14; -#endif - -/** - * @brief PWMD15 driver identifier. - * @note The driver PWMD15 allocates the timer TIM15 when enabled. - */ -#if STM32_PWM_USE_TIM15 || defined(__DOXYGEN__) -PWMDriver PWMD15; -#endif - -/** - * @brief PWMD16 driver identifier. - * @note The driver PWMD16 allocates the timer TIM16 when enabled. - */ -#if STM32_PWM_USE_TIM16 || defined(__DOXYGEN__) -PWMDriver PWMD16; -#endif - -/** - * @brief PWMD17 driver identifier. - * @note The driver PWMD17 allocates the timer TIM17 when enabled. - */ -#if STM32_PWM_USE_TIM17 || defined(__DOXYGEN__) -PWMDriver PWMD17; -#endif - -/** - * @brief PWMD20 driver identifier. - * @note The driver PWMD20 allocates the timer TIM20 when enabled. - */ -#if STM32_PWM_USE_TIM20 || defined(__DOXYGEN__) -PWMDriver PWMD20; -#endif - -/** - * @brief PWMD21 driver identifier. - * @note The driver PWMD21 allocates the timer TIM21 when enabled. - */ -#if STM32_PWM_USE_TIM21 || defined(__DOXYGEN__) -PWMDriver PWMD21; -#endif - -/** - * @brief PWMD22 driver identifier. - * @note The driver PWMD22 allocates the timer TIM22 when enabled. - */ -#if STM32_PWM_USE_TIM22 || defined(__DOXYGEN__) -PWMDriver PWMD22; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) -#if !defined(STM32_TIM1_SUPPRESS_ISR) -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 update interrupt handler. - * @note It is assumed that this interrupt is only activated if the callback - * pointer is not equal to @p NULL in order to not perform an extra - * check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD1); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM1 */ - -#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) -#if !defined(STM32_TIM2_SUPPRESS_ISR) -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM2 */ - -#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) -#if !defined(STM32_TIM3_SUPPRESS_ISR) -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM3 */ - -#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) -#if !defined(STM32_TIM4_SUPPRESS_ISR) -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM4 */ - -#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) -#if !defined(STM32_TIM5_SUPPRESS_ISR) -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM5 */ - -#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) -#if !defined(STM32_TIM8_SUPPRESS_ISR) -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 update interrupt handler. - * @note It is assumed that this interrupt is only activated if the callback - * pointer is not equal to @p NULL in order to not perform an extra - * check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD8); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM8 */ - -#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -#if !defined(STM32_TIM9_SUPPRESS_ISR) -#error "TIM9 ISR not defined by platform" -#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM9 */ - -#if STM32_PWM_USE_TIM10 || defined(__DOXYGEN__) -#if !defined(STM32_TIM10_SUPPRESS_ISR) -#error "TIM10 ISR not defined by platform" -#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM10 */ - -#if STM32_PWM_USE_TIM11 || defined(__DOXYGEN__) -#if !defined(STM32_TIM11_SUPPRESS_ISR) -#error "TIM11 ISR not defined by platform" -#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM11 */ - -#if STM32_PWM_USE_TIM12 || defined(__DOXYGEN__) -#if !defined(STM32_TIM12_SUPPRESS_ISR) -#error "TIM12 ISR not defined by platform" -#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM12 */ - -#if STM32_PWM_USE_TIM13 || defined(__DOXYGEN__) -#if !defined(STM32_TIM13_SUPPRESS_ISR) -#error "TIM13 ISR not defined by platform" -#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM13 */ - -#if STM32_PWM_USE_TIM14 || defined(__DOXYGEN__) -#if !defined(STM32_TIM14_SUPPRESS_ISR) -#error "TIM14 ISR not defined by platform" -#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM14 */ - -#if STM32_PWM_USE_TIM15 || defined(__DOXYGEN__) -#if !defined(STM32_TIM15_SUPPRESS_ISR) -#error "TIM15 ISR not defined by platform" -#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM15 */ - -#if STM32_PWM_USE_TIM16 || defined(__DOXYGEN__) -#if !defined(STM32_TIM16_SUPPRESS_ISR) -#error "TIM16 ISR not defined by platform" -#endif /* !defined(STM32_TIM16_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM16 */ - -#if STM32_PWM_USE_TIM17 || defined(__DOXYGEN__) -#if !defined(STM32_TIM17_SUPPRESS_ISR) -#error "TIM17 ISR not defined by platform" -#endif /* !defined(STM32_TIM17_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM17 */ - -#if STM32_PWM_USE_TIM20 || defined(__DOXYGEN__) -#if !defined(STM32_TIM20_SUPPRESS_ISR) -#error "TIM20 ISR not defined by platform" -#endif /* !defined(STM32_TIM20_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM20 */ - -#if STM32_PWM_USE_TIM21 || defined(__DOXYGEN__) -#if !defined(STM32_TIM21_SUPPRESS_ISR) -#error "TIM21 ISR not defined by platform" -#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM21 */ - -#if STM32_PWM_USE_TIM22 || defined(__DOXYGEN__) -#if !defined(STM32_TIM22_SUPPRESS_ISR) -#error "TIM22 ISR not defined by platform" -#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM22 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level PWM driver initialization. - * - * @notapi - */ -void pwm_lld_init(void) { - -#if STM32_PWM_USE_TIM1 - /* Driver initialization.*/ - pwmObjectInit(&PWMD1); - PWMD1.channels = STM32_TIM1_CHANNELS; - PWMD1.tim = STM32_TIM1; -#endif - -#if STM32_PWM_USE_TIM2 - /* Driver initialization.*/ - pwmObjectInit(&PWMD2); - PWMD2.channels = STM32_TIM2_CHANNELS; - PWMD2.tim = STM32_TIM2; -#endif - -#if STM32_PWM_USE_TIM3 - /* Driver initialization.*/ - pwmObjectInit(&PWMD3); - PWMD3.channels = STM32_TIM3_CHANNELS; - PWMD3.tim = STM32_TIM3; -#endif - -#if STM32_PWM_USE_TIM4 - /* Driver initialization.*/ - pwmObjectInit(&PWMD4); - PWMD4.channels = STM32_TIM4_CHANNELS; - PWMD4.tim = STM32_TIM4; -#endif - -#if STM32_PWM_USE_TIM5 - /* Driver initialization.*/ - pwmObjectInit(&PWMD5); - PWMD5.channels = STM32_TIM5_CHANNELS; - PWMD5.tim = STM32_TIM5; -#endif - -#if STM32_PWM_USE_TIM8 - /* Driver initialization.*/ - pwmObjectInit(&PWMD8); - PWMD8.channels = STM32_TIM8_CHANNELS; - PWMD8.tim = STM32_TIM8; -#endif - -#if STM32_PWM_USE_TIM9 - /* Driver initialization.*/ - pwmObjectInit(&PWMD9); - PWMD9.channels = STM32_TIM9_CHANNELS; - PWMD9.tim = STM32_TIM9; -#endif - -#if STM32_PWM_USE_TIM10 - /* Driver initialization.*/ - pwmObjectInit(&PWMD10); - PWMD10.channels = STM32_TIM10_CHANNELS; - PWMD10.tim = STM32_TIM10; -#endif - -#if STM32_PWM_USE_TIM11 - /* Driver initialization.*/ - pwmObjectInit(&PWMD11); - PWMD11.channels = STM32_TIM11_CHANNELS; - PWMD11.tim = STM32_TIM11; -#endif - -#if STM32_PWM_USE_TIM12 - /* Driver initialization.*/ - pwmObjectInit(&PWMD12); - PWMD12.channels = STM32_TIM12_CHANNELS; - PWMD12.tim = STM32_TIM12; -#endif - -#if STM32_PWM_USE_TIM13 - /* Driver initialization.*/ - pwmObjectInit(&PWMD13); - PWMD13.channels = STM32_TIM13_CHANNELS; - PWMD13.tim = STM32_TIM13; -#endif - -#if STM32_PWM_USE_TIM14 - /* Driver initialization.*/ - pwmObjectInit(&PWMD14); - PWMD14.channels = STM32_TIM14_CHANNELS; - PWMD14.tim = STM32_TIM14; -#endif - -#if STM32_PWM_USE_TIM15 - /* Driver initialization.*/ - pwmObjectInit(&PWMD15); - PWMD15.channels = STM32_TIM15_CHANNELS; - PWMD15.tim = STM32_TIM15; -#endif - -#if STM32_PWM_USE_TIM16 - /* Driver initialization.*/ - pwmObjectInit(&PWMD16); - PWMD16.channels = STM32_TIM16_CHANNELS; - PWMD16.tim = STM32_TIM16; -#endif - -#if STM32_PWM_USE_TIM17 - /* Driver initialization.*/ - pwmObjectInit(&PWMD17); - PWMD17.channels = STM32_TIM17_CHANNELS; - PWMD17.tim = STM32_TIM17; -#endif - -#if STM32_PWM_USE_TIM20 - /* Driver initialization.*/ - pwmObjectInit(&PWMD20); - PWMD20.channels = STM32_TIM20_CHANNELS; - PWMD20.tim = STM32_TIM20; -#endif - -#if STM32_PWM_USE_TIM21 - /* Driver initialization.*/ - pwmObjectInit(&PWMD21); - PWMD21.channels = STM32_TIM21_CHANNELS; - PWMD21.tim = STM32_TIM21; -#endif - -#if STM32_PWM_USE_TIM22 - /* Driver initialization.*/ - pwmObjectInit(&PWMD22); - PWMD22.channels = STM32_TIM22_CHANNELS; - PWMD22.tim = STM32_TIM22; -#endif -} - -/** - * @brief Configures and activates the PWM peripheral. - * @note Starting a driver that is already in the @p PWM_READY state - * disables all the active channels. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_start(PWMDriver *pwmp) { - uint32_t psc; - uint32_t ccer; - - if (pwmp->state == PWM_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { - rccEnableTIM1(true); - rccResetTIM1(); -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM1CLK) - pwmp->clock = STM32_TIM1CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { - rccEnableTIM2(true); - rccResetTIM2(); -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM2CLK) - pwmp->clock = STM32_TIM2CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { - rccEnableTIM3(true); - rccResetTIM3(); -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM3CLK) - pwmp->clock = STM32_TIM3CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { - rccEnableTIM4(true); - rccResetTIM4(); -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM4CLK) - pwmp->clock = STM32_TIM4CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { - rccEnableTIM5(true); - rccResetTIM5(); -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM5CLK) - pwmp->clock = STM32_TIM5CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { - rccEnableTIM8(true); - rccResetTIM8(); -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM8CLK) - pwmp->clock = STM32_TIM8CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - rccEnableTIM9(true); - rccResetTIM9(); -#if defined(STM32_TIM9CLK) - pwmp->clock = STM32_TIM9CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM10 - if (&PWMD10 == pwmp) { - rccEnableTIM10(true); - rccResetTIM10(); -#if defined(STM32_TIM10CLK) - pwmp->clock = STM32_TIM10CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM11 - if (&PWMD11 == pwmp) { - rccEnableTIM11(true); - rccResetTIM11(); -#if defined(STM32_TIM11CLK) - pwmp->clock = STM32_TIM11CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM12 - if (&PWMD12 == pwmp) { - rccEnableTIM12(true); - rccResetTIM12(); -#if defined(STM32_TIM12CLK) - pwmp->clock = STM32_TIM12CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM13 - if (&PWMD13 == pwmp) { - rccEnableTIM13(true); - rccResetTIM13(); -#if defined(STM32_TIM13CLK) - pwmp->clock = STM32_TIM13CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM14 - if (&PWMD14 == pwmp) { - rccEnableTIM14(true); - rccResetTIM14(); -#if defined(STM32_TIM14CLK) - pwmp->clock = STM32_TIM14CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM15 - if (&PWMD15 == pwmp) { - rccEnableTIM15(true); - rccResetTIM15(); -#if defined(STM32_TIM15CLK) - pwmp->clock = STM32_TIM15CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM16 - if (&PWMD16 == pwmp) { - rccEnableTIM16(true); - rccResetTIM16(); -#if defined(STM32_TIM16CLK) - pwmp->clock = STM32_TIM16CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM17 - if (&PWMD17 == pwmp) { - rccEnableTIM17(true); - rccResetTIM17(); -#if defined(STM32_TIM17CLK) - pwmp->clock = STM32_TIM17CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM20 - if (&PWMD20 == pwmp) { - rccEnableTIM20(true); - rccResetTIM20(); -#if defined(STM32_TIM20CLK) - pwmp->clock = STM32_TIM20CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM21 - if (&PWMD21 == pwmp) { - rccEnableTIM21(true); - rccResetTIM21(); -#if defined(STM32_TIM21CLK) - pwmp->clock = STM32_TIM21CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM22 - if (&PWMD22 == pwmp) { - rccEnableTIM22(true); - rccResetTIM22(); -#if defined(STM32_TIM22CLK) - pwmp->clock = STM32_TIM22CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - - /* All channels configured in PWM1 mode with preload enabled and will - stay that way until the driver is stopped.*/ - pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE | - STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE; - pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE | - STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE; -#if STM32_TIM_MAX_CHANNELS > 4 - pwmp->tim->CCMR3 = STM32_TIM_CCMR3_OC5M(6) | STM32_TIM_CCMR3_OC5PE | - STM32_TIM_CCMR3_OC6M(6) | STM32_TIM_CCMR3_OC6PE; -#endif - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - pwmp->tim->CR1 = 0; /* Timer disabled. */ - pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ - pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ - pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ - pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ -#if STM32_TIM_MAX_CHANNELS > 4 - if (pwmp->channels > 4) { - pwmp->tim->CCXR[0] = 0; /* Comparator 5 disabled. */ - pwmp->tim->CCXR[1] = 0; /* Comparator 6 disabled. */ - } -#endif - pwmp->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - psc = (pwmp->clock / pwmp->config->frequency) - 1; - osalDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * pwmp->config->frequency) == pwmp->clock, - "invalid frequency"); - pwmp->tim->PSC = psc; - pwmp->tim->ARR = pwmp->period - 1; - pwmp->tim->CR2 = pwmp->config->cr2; - - /* Output enables and polarities setup.*/ - ccer = 0; - switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC1P; - /* Falls through.*/ - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC1E; - /* Falls through.*/ - default: - ; - } - switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC2P; - /* Falls through.*/ - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC2E; - /* Falls through.*/ - default: - ; - } - switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC3P; - /* Falls through.*/ - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC3E; - /* Falls through.*/ - default: - ; - } - switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC4P; - /* Falls through.*/ - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC4E; - /* Falls through.*/ - default: - ; - } -#if STM32_PWM_USE_ADVANCED -#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20 - if (&PWMD1 == pwmp) { -#endif -#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20 - if (&PWMD8 == pwmp) { -#endif -#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20 - if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) { -#endif -#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 - if (&PWMD20 == pwmp) { -#endif -#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 - if ((&PWMD1 == pwmp) || (&PWMD20 == pwmp)) { -#endif -#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 - if ((&PWMD8 == pwmp) || (&PWMD20 == pwmp)) { -#endif -#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 - if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp) || (&PWMD20 == pwmp)) { -#endif - switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC1NP; - /* Falls through.*/ - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC1NE; - /* Falls through.*/ - default: - ; - } - switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC2NP; - /* Falls through.*/ - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC2NE; - /* Falls through.*/ - default: - ; - } - switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC3NP; - /* Falls through.*/ - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC3NE; - /* Falls through.*/ - default: - ; - } - switch (pwmp->config->channels[3].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC4NP; - /* Falls through.*/ - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC4NE; - /* Falls through.*/ - default: - ; - } - } -#endif /* STM32_PWM_USE_ADVANCED*/ - - pwmp->tim->CCER = ccer; - pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - pwmp->tim->SR = 0; /* Clear pending IRQs. */ - pwmp->tim->DIER = pwmp->config->dier & /* DMA-related DIER settings. */ - ~STM32_TIM_DIER_IRQ_MASK; -#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 || STM32_PWM_USE_TIM20 -#if STM32_PWM_USE_ADVANCED - pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE; -#else - pwmp->tim->BDTR = STM32_TIM_BDTR_MOE; -#endif -#endif - /* Timer configured and started.*/ - pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | - STM32_TIM_CR1_CEN; -} - -/** - * @brief Deactivates the PWM peripheral. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_stop(PWMDriver *pwmp) { - - /* If in ready state then disables the PWM clock.*/ - if (pwmp->state == PWM_READY) { - pwmp->tim->CR1 = 0; /* Timer disabled. */ - pwmp->tim->DIER = 0; /* All IRQs disabled. */ - pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ -#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 || STM32_PWM_USE_TIM20 - pwmp->tim->BDTR = 0; -#endif - -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); -#endif - rccDisableTIM1(); - } -#endif - -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM2_NUMBER); -#endif - rccDisableTIM2(); - } -#endif - -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM3_NUMBER); -#endif - rccDisableTIM3(); - } -#endif - -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM4_NUMBER); -#endif - rccDisableTIM4(); - } -#endif - -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM5_NUMBER); -#endif - rccDisableTIM5(); - } -#endif - -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); -#endif - rccDisableTIM8(); - } -#endif - -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - rccDisableTIM9(); - } -#endif - -#if STM32_PWM_USE_TIM10 - if (&PWMD10 == pwmp) { - rccDisableTIM10(); - } -#endif - -#if STM32_PWM_USE_TIM11 - if (&PWMD11 == pwmp) { - rccDisableTIM11(); - } -#endif - -#if STM32_PWM_USE_TIM12 - if (&PWMD12 == pwmp) { - rccDisableTIM12(); - } -#endif - -#if STM32_PWM_USE_TIM13 - if (&PWMD13 == pwmp) { - rccDisableTIM13(); - } -#endif - -#if STM32_PWM_USE_TIM14 - if (&PWMD14 == pwmp) { - rccDisableTIM14(); - } -#endif - -#if STM32_PWM_USE_TIM15 - if (&PWMD15 == pwmp) { - rccDisableTIM15(); - } -#endif - -#if STM32_PWM_USE_TIM16 - if (&PWMD16 == pwmp) { - rccDisableTIM16(); - } -#endif - -#if STM32_PWM_USE_TIM17 - if (&PWMD17 == pwmp) { - rccDisableTIM17(); - } -#endif - -#if STM32_PWM_USE_TIM20 - if (&PWMD20 == pwmp) { - rccDisableTIM20(); - } -#endif - -#if STM32_PWM_USE_TIM21 - if (&PWMD21 == pwmp) { - rccDisableTIM21(); - } -#endif - -#if STM32_PWM_USE_TIM22 - if (&PWMD22 == pwmp) { - rccDisableTIM22(); - } -#endif - } -} - -/** - * @brief Enables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is active using the specified configuration. - * @note The function has effect at the next cycle start. - * @note Channel notification is not enabled. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * @param[in] width PWM pulse width as clock pulses number - * - * @notapi - */ -void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width) { - - /* Changing channel duty cycle on the fly.*/ -#if STM32_TIM_MAX_CHANNELS <= 4 - pwmp->tim->CCR[channel] = width; -#else - if (channel < 4) - pwmp->tim->CCR[channel] = width; - else - pwmp->tim->CCXR[channel - 4] = width; -#endif -} - -/** - * @brief Disables a PWM channel and its notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is disabled and its output line returned to the - * idle state. - * @note The function has effect at the next cycle start. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @notapi - */ -void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { - -#if STM32_TIM_MAX_CHANNELS <= 4 - pwmp->tim->CCR[channel] = 0; - pwmp->tim->DIER &= ~(2 << channel); -#else - if (channel < 4) { - pwmp->tim->CCR[channel] = 0; - pwmp->tim->DIER &= ~(2 << channel); - } - else - pwmp->tim->CCXR[channel - 4] = 0; -#endif -} - -/** - * @brief Enables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) { - uint32_t dier = pwmp->tim->DIER; - - /* If the IRQ is not already enabled care must be taken to clear it, - it is probably already pending because the timer is running.*/ - if ((dier & STM32_TIM_DIER_UIE) == 0) { - pwmp->tim->SR = ~STM32_TIM_SR_UIF; - pwmp->tim->DIER = dier | STM32_TIM_DIER_UIE; - } -} - -/** - * @brief Disables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { - - pwmp->tim->DIER &= ~STM32_TIM_DIER_UIE; -} - -/** - * @brief Enables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @notapi - */ -void pwm_lld_enable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel) { - uint32_t dier = pwmp->tim->DIER; - -#if STM32_TIM_MAX_CHANNELS > 4 - /* Channels 4 and 5 do not support callbacks.*/ - osalDbgAssert(channel < 4, "callback not supported"); -#endif - - /* If the IRQ is not already enabled care must be taken to clear it, - it is probably already pending because the timer is running.*/ - if ((dier & (2 << channel)) == 0) { - pwmp->tim->SR = ~(2 << channel); - pwmp->tim->DIER = dier | (2 << channel); - } -} - -/** - * @brief Disables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @notapi - */ -void pwm_lld_disable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel) { - - pwmp->tim->DIER &= ~(2 << channel); -} - -/** - * @brief Common TIM2...TIM5,TIM9 IRQ handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_serve_interrupt(PWMDriver *pwmp) { - uint32_t sr; - - sr = pwmp->tim->SR; - sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - pwmp->tim->SR = ~sr; - if (((sr & STM32_TIM_SR_CC1IF) != 0) && - (pwmp->config->channels[0].callback != NULL)) - pwmp->config->channels[0].callback(pwmp); - if (((sr & STM32_TIM_SR_CC2IF) != 0) && - (pwmp->config->channels[1].callback != NULL)) - pwmp->config->channels[1].callback(pwmp); - if (((sr & STM32_TIM_SR_CC3IF) != 0) && - (pwmp->config->channels[2].callback != NULL)) - pwmp->config->channels[2].callback(pwmp); - if (((sr & STM32_TIM_SR_CC4IF) != 0) && - (pwmp->config->channels[3].callback != NULL)) - pwmp->config->channels[3].callback(pwmp); - if (((sr & STM32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL)) - pwmp->config->callback(pwmp); -} - -#endif /* HAL_USE_PWM */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_pwm_lld.c + * @brief STM32 PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief PWMD1 driver identifier. + * @note The driver PWMD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) +PWMDriver PWMD1; +#endif + +/** + * @brief PWMD2 driver identifier. + * @note The driver PWMD2 allocates the timer TIM2 when enabled. + */ +#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) +PWMDriver PWMD2; +#endif + +/** + * @brief PWMD3 driver identifier. + * @note The driver PWMD3 allocates the timer TIM3 when enabled. + */ +#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) +PWMDriver PWMD3; +#endif + +/** + * @brief PWMD4 driver identifier. + * @note The driver PWMD4 allocates the timer TIM4 when enabled. + */ +#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) +PWMDriver PWMD4; +#endif + +/** + * @brief PWMD5 driver identifier. + * @note The driver PWMD5 allocates the timer TIM5 when enabled. + */ +#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) +PWMDriver PWMD5; +#endif + +/** + * @brief PWMD8 driver identifier. + * @note The driver PWMD8 allocates the timer TIM8 when enabled. + */ +#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) +PWMDriver PWMD8; +#endif + +/** + * @brief PWMD9 driver identifier. + * @note The driver PWMD9 allocates the timer TIM9 when enabled. + */ +#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +PWMDriver PWMD9; +#endif + +/** + * @brief PWMD10 driver identifier. + * @note The driver PWMD10 allocates the timer TIM10 when enabled. + */ +#if STM32_PWM_USE_TIM10 || defined(__DOXYGEN__) +PWMDriver PWMD10; +#endif + +/** + * @brief PWMD11 driver identifier. + * @note The driver PWMD11 allocates the timer TIM11 when enabled. + */ +#if STM32_PWM_USE_TIM11 || defined(__DOXYGEN__) +PWMDriver PWMD11; +#endif + +/** + * @brief PWMD12 driver identifier. + * @note The driver PWMD12 allocates the timer TIM12 when enabled. + */ +#if STM32_PWM_USE_TIM12 || defined(__DOXYGEN__) +PWMDriver PWMD12; +#endif + +/** + * @brief PWMD13 driver identifier. + * @note The driver PWMD13 allocates the timer TIM13 when enabled. + */ +#if STM32_PWM_USE_TIM13 || defined(__DOXYGEN__) +PWMDriver PWMD13; +#endif + +/** + * @brief PWMD14 driver identifier. + * @note The driver PWMD14 allocates the timer TIM14 when enabled. + */ +#if STM32_PWM_USE_TIM14 || defined(__DOXYGEN__) +PWMDriver PWMD14; +#endif + +/** + * @brief PWMD15 driver identifier. + * @note The driver PWMD15 allocates the timer TIM15 when enabled. + */ +#if STM32_PWM_USE_TIM15 || defined(__DOXYGEN__) +PWMDriver PWMD15; +#endif + +/** + * @brief PWMD16 driver identifier. + * @note The driver PWMD16 allocates the timer TIM16 when enabled. + */ +#if STM32_PWM_USE_TIM16 || defined(__DOXYGEN__) +PWMDriver PWMD16; +#endif + +/** + * @brief PWMD17 driver identifier. + * @note The driver PWMD17 allocates the timer TIM17 when enabled. + */ +#if STM32_PWM_USE_TIM17 || defined(__DOXYGEN__) +PWMDriver PWMD17; +#endif + +/** + * @brief PWMD20 driver identifier. + * @note The driver PWMD20 allocates the timer TIM20 when enabled. + */ +#if STM32_PWM_USE_TIM20 || defined(__DOXYGEN__) +PWMDriver PWMD20; +#endif + +/** + * @brief PWMD21 driver identifier. + * @note The driver PWMD21 allocates the timer TIM21 when enabled. + */ +#if STM32_PWM_USE_TIM21 || defined(__DOXYGEN__) +PWMDriver PWMD21; +#endif + +/** + * @brief PWMD22 driver identifier. + * @note The driver PWMD22 allocates the timer TIM22 when enabled. + */ +#if STM32_PWM_USE_TIM22 || defined(__DOXYGEN__) +PWMDriver PWMD22; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) +#if !defined(STM32_TIM1_SUPPRESS_ISR) +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 update interrupt handler. + * @note It is assumed that this interrupt is only activated if the callback + * pointer is not equal to @p NULL in order to not perform an extra + * check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD1); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM1 */ + +#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) +#if !defined(STM32_TIM2_SUPPRESS_ISR) +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM2 */ + +#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) +#if !defined(STM32_TIM3_SUPPRESS_ISR) +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM3 */ + +#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) +#if !defined(STM32_TIM4_SUPPRESS_ISR) +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM4 */ + +#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) +#if !defined(STM32_TIM5_SUPPRESS_ISR) +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM5 */ + +#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) +#if !defined(STM32_TIM8_SUPPRESS_ISR) +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 update interrupt handler. + * @note It is assumed that this interrupt is only activated if the callback + * pointer is not equal to @p NULL in order to not perform an extra + * check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD8); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM8 */ + +#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +#if !defined(STM32_TIM9_SUPPRESS_ISR) +#error "TIM9 ISR not defined by platform" +#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM9 */ + +#if STM32_PWM_USE_TIM10 || defined(__DOXYGEN__) +#if !defined(STM32_TIM10_SUPPRESS_ISR) +#error "TIM10 ISR not defined by platform" +#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM10 */ + +#if STM32_PWM_USE_TIM11 || defined(__DOXYGEN__) +#if !defined(STM32_TIM11_SUPPRESS_ISR) +#error "TIM11 ISR not defined by platform" +#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM11 */ + +#if STM32_PWM_USE_TIM12 || defined(__DOXYGEN__) +#if !defined(STM32_TIM12_SUPPRESS_ISR) +#error "TIM12 ISR not defined by platform" +#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM12 */ + +#if STM32_PWM_USE_TIM13 || defined(__DOXYGEN__) +#if !defined(STM32_TIM13_SUPPRESS_ISR) +#error "TIM13 ISR not defined by platform" +#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM13 */ + +#if STM32_PWM_USE_TIM14 || defined(__DOXYGEN__) +#if !defined(STM32_TIM14_SUPPRESS_ISR) +#error "TIM14 ISR not defined by platform" +#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM14 */ + +#if STM32_PWM_USE_TIM15 || defined(__DOXYGEN__) +#if !defined(STM32_TIM15_SUPPRESS_ISR) +#error "TIM15 ISR not defined by platform" +#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM15 */ + +#if STM32_PWM_USE_TIM16 || defined(__DOXYGEN__) +#if !defined(STM32_TIM16_SUPPRESS_ISR) +#error "TIM16 ISR not defined by platform" +#endif /* !defined(STM32_TIM16_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM16 */ + +#if STM32_PWM_USE_TIM17 || defined(__DOXYGEN__) +#if !defined(STM32_TIM17_SUPPRESS_ISR) +#error "TIM17 ISR not defined by platform" +#endif /* !defined(STM32_TIM17_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM17 */ + +#if STM32_PWM_USE_TIM20 || defined(__DOXYGEN__) +#if !defined(STM32_TIM20_SUPPRESS_ISR) +#error "TIM20 ISR not defined by platform" +#endif /* !defined(STM32_TIM20_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM20 */ + +#if STM32_PWM_USE_TIM21 || defined(__DOXYGEN__) +#if !defined(STM32_TIM21_SUPPRESS_ISR) +#error "TIM21 ISR not defined by platform" +#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM21 */ + +#if STM32_PWM_USE_TIM22 || defined(__DOXYGEN__) +#if !defined(STM32_TIM22_SUPPRESS_ISR) +#error "TIM22 ISR not defined by platform" +#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM22 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level PWM driver initialization. + * + * @notapi + */ +void pwm_lld_init(void) { + +#if STM32_PWM_USE_TIM1 + /* Driver initialization.*/ + pwmObjectInit(&PWMD1); + PWMD1.channels = STM32_TIM1_CHANNELS; + PWMD1.tim = STM32_TIM1; +#endif + +#if STM32_PWM_USE_TIM2 + /* Driver initialization.*/ + pwmObjectInit(&PWMD2); + PWMD2.channels = STM32_TIM2_CHANNELS; + PWMD2.tim = STM32_TIM2; +#endif + +#if STM32_PWM_USE_TIM3 + /* Driver initialization.*/ + pwmObjectInit(&PWMD3); + PWMD3.channels = STM32_TIM3_CHANNELS; + PWMD3.tim = STM32_TIM3; +#endif + +#if STM32_PWM_USE_TIM4 + /* Driver initialization.*/ + pwmObjectInit(&PWMD4); + PWMD4.channels = STM32_TIM4_CHANNELS; + PWMD4.tim = STM32_TIM4; +#endif + +#if STM32_PWM_USE_TIM5 + /* Driver initialization.*/ + pwmObjectInit(&PWMD5); + PWMD5.channels = STM32_TIM5_CHANNELS; + PWMD5.tim = STM32_TIM5; +#endif + +#if STM32_PWM_USE_TIM8 + /* Driver initialization.*/ + pwmObjectInit(&PWMD8); + PWMD8.channels = STM32_TIM8_CHANNELS; + PWMD8.tim = STM32_TIM8; +#endif + +#if STM32_PWM_USE_TIM9 + /* Driver initialization.*/ + pwmObjectInit(&PWMD9); + PWMD9.channels = STM32_TIM9_CHANNELS; + PWMD9.tim = STM32_TIM9; +#endif + +#if STM32_PWM_USE_TIM10 + /* Driver initialization.*/ + pwmObjectInit(&PWMD10); + PWMD10.channels = STM32_TIM10_CHANNELS; + PWMD10.tim = STM32_TIM10; +#endif + +#if STM32_PWM_USE_TIM11 + /* Driver initialization.*/ + pwmObjectInit(&PWMD11); + PWMD11.channels = STM32_TIM11_CHANNELS; + PWMD11.tim = STM32_TIM11; +#endif + +#if STM32_PWM_USE_TIM12 + /* Driver initialization.*/ + pwmObjectInit(&PWMD12); + PWMD12.channels = STM32_TIM12_CHANNELS; + PWMD12.tim = STM32_TIM12; +#endif + +#if STM32_PWM_USE_TIM13 + /* Driver initialization.*/ + pwmObjectInit(&PWMD13); + PWMD13.channels = STM32_TIM13_CHANNELS; + PWMD13.tim = STM32_TIM13; +#endif + +#if STM32_PWM_USE_TIM14 + /* Driver initialization.*/ + pwmObjectInit(&PWMD14); + PWMD14.channels = STM32_TIM14_CHANNELS; + PWMD14.tim = STM32_TIM14; +#endif + +#if STM32_PWM_USE_TIM15 + /* Driver initialization.*/ + pwmObjectInit(&PWMD15); + PWMD15.channels = STM32_TIM15_CHANNELS; + PWMD15.tim = STM32_TIM15; +#endif + +#if STM32_PWM_USE_TIM16 + /* Driver initialization.*/ + pwmObjectInit(&PWMD16); + PWMD16.channels = STM32_TIM16_CHANNELS; + PWMD16.tim = STM32_TIM16; +#endif + +#if STM32_PWM_USE_TIM17 + /* Driver initialization.*/ + pwmObjectInit(&PWMD17); + PWMD17.channels = STM32_TIM17_CHANNELS; + PWMD17.tim = STM32_TIM17; +#endif + +#if STM32_PWM_USE_TIM20 + /* Driver initialization.*/ + pwmObjectInit(&PWMD20); + PWMD20.channels = STM32_TIM20_CHANNELS; + PWMD20.tim = STM32_TIM20; +#endif + +#if STM32_PWM_USE_TIM21 + /* Driver initialization.*/ + pwmObjectInit(&PWMD21); + PWMD21.channels = STM32_TIM21_CHANNELS; + PWMD21.tim = STM32_TIM21; +#endif + +#if STM32_PWM_USE_TIM22 + /* Driver initialization.*/ + pwmObjectInit(&PWMD22); + PWMD22.channels = STM32_TIM22_CHANNELS; + PWMD22.tim = STM32_TIM22; +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_start(PWMDriver *pwmp) { + uint32_t psc; + uint32_t ccer; + + if (pwmp->state == PWM_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { + rccEnableTIM1(true); + rccResetTIM1(); +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM1CLK) + pwmp->clock = STM32_TIM1CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { + rccEnableTIM2(true); + rccResetTIM2(); +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM2CLK) + pwmp->clock = STM32_TIM2CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { + rccEnableTIM3(true); + rccResetTIM3(); +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM3CLK) + pwmp->clock = STM32_TIM3CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { + rccEnableTIM4(true); + rccResetTIM4(); +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM4CLK) + pwmp->clock = STM32_TIM4CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { + rccEnableTIM5(true); + rccResetTIM5(); +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM5CLK) + pwmp->clock = STM32_TIM5CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { + rccEnableTIM8(true); + rccResetTIM8(); +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM8CLK) + pwmp->clock = STM32_TIM8CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + rccEnableTIM9(true); + rccResetTIM9(); +#if defined(STM32_TIM9CLK) + pwmp->clock = STM32_TIM9CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM10 + if (&PWMD10 == pwmp) { + rccEnableTIM10(true); + rccResetTIM10(); +#if defined(STM32_TIM10CLK) + pwmp->clock = STM32_TIM10CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM11 + if (&PWMD11 == pwmp) { + rccEnableTIM11(true); + rccResetTIM11(); +#if defined(STM32_TIM11CLK) + pwmp->clock = STM32_TIM11CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM12 + if (&PWMD12 == pwmp) { + rccEnableTIM12(true); + rccResetTIM12(); +#if defined(STM32_TIM12CLK) + pwmp->clock = STM32_TIM12CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM13 + if (&PWMD13 == pwmp) { + rccEnableTIM13(true); + rccResetTIM13(); +#if defined(STM32_TIM13CLK) + pwmp->clock = STM32_TIM13CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM14 + if (&PWMD14 == pwmp) { + rccEnableTIM14(true); + rccResetTIM14(); +#if defined(STM32_TIM14CLK) + pwmp->clock = STM32_TIM14CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM15 + if (&PWMD15 == pwmp) { + rccEnableTIM15(true); + rccResetTIM15(); +#if defined(STM32_TIM15CLK) + pwmp->clock = STM32_TIM15CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM16 + if (&PWMD16 == pwmp) { + rccEnableTIM16(true); + rccResetTIM16(); +#if defined(STM32_TIM16CLK) + pwmp->clock = STM32_TIM16CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM17 + if (&PWMD17 == pwmp) { + rccEnableTIM17(true); + rccResetTIM17(); +#if defined(STM32_TIM17CLK) + pwmp->clock = STM32_TIM17CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM20 + if (&PWMD20 == pwmp) { + rccEnableTIM20(true); + rccResetTIM20(); +#if defined(STM32_TIM20CLK) + pwmp->clock = STM32_TIM20CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM21 + if (&PWMD21 == pwmp) { + rccEnableTIM21(true); + rccResetTIM21(); +#if defined(STM32_TIM21CLK) + pwmp->clock = STM32_TIM21CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM22 + if (&PWMD22 == pwmp) { + rccEnableTIM22(true); + rccResetTIM22(); +#if defined(STM32_TIM22CLK) + pwmp->clock = STM32_TIM22CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + + /* All channels configured in PWM1 mode with preload enabled and will + stay that way until the driver is stopped.*/ + pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE | + STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE; + pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE | + STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE; +#if STM32_TIM_MAX_CHANNELS > 4 + pwmp->tim->CCMR3 = STM32_TIM_CCMR3_OC5M(6) | STM32_TIM_CCMR3_OC5PE | + STM32_TIM_CCMR3_OC6M(6) | STM32_TIM_CCMR3_OC6PE; +#endif + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + pwmp->tim->CR1 = 0; /* Timer disabled. */ + pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ + pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ + pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ + pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ +#if STM32_TIM_MAX_CHANNELS > 4 + if (pwmp->channels > 4) { + pwmp->tim->CCXR[0] = 0; /* Comparator 5 disabled. */ + pwmp->tim->CCXR[1] = 0; /* Comparator 6 disabled. */ + } +#endif + pwmp->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + psc = (pwmp->clock / pwmp->config->frequency) - 1; + osalDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * pwmp->config->frequency) == pwmp->clock, + "invalid frequency"); + pwmp->tim->PSC = psc; + pwmp->tim->ARR = pwmp->period - 1; + pwmp->tim->CR2 = pwmp->config->cr2; + + /* Output enables and polarities setup.*/ + ccer = 0; + switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC1P; + /* Falls through.*/ + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC1E; + /* Falls through.*/ + default: + ; + } + switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC2P; + /* Falls through.*/ + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC2E; + /* Falls through.*/ + default: + ; + } + switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC3P; + /* Falls through.*/ + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC3E; + /* Falls through.*/ + default: + ; + } + switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC4P; + /* Falls through.*/ + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC4E; + /* Falls through.*/ + default: + ; + } +#if STM32_PWM_USE_ADVANCED +#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20 + if (&PWMD1 == pwmp) { +#endif +#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20 + if (&PWMD8 == pwmp) { +#endif +#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20 + if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) { +#endif +#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 + if (&PWMD20 == pwmp) { +#endif +#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 + if ((&PWMD1 == pwmp) || (&PWMD20 == pwmp)) { +#endif +#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 + if ((&PWMD8 == pwmp) || (&PWMD20 == pwmp)) { +#endif +#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20 + if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp) || (&PWMD20 == pwmp)) { +#endif + switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC1NP; + /* Falls through.*/ + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC1NE; + /* Falls through.*/ + default: + ; + } + switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC2NP; + /* Falls through.*/ + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC2NE; + /* Falls through.*/ + default: + ; + } + switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC3NP; + /* Falls through.*/ + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC3NE; + /* Falls through.*/ + default: + ; + } + switch (pwmp->config->channels[3].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC4NP; + /* Falls through.*/ + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC4NE; + /* Falls through.*/ + default: + ; + } + } +#endif /* STM32_PWM_USE_ADVANCED*/ + + pwmp->tim->CCER = ccer; + pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + pwmp->tim->SR = 0; /* Clear pending IRQs. */ + pwmp->tim->DIER = pwmp->config->dier & /* DMA-related DIER settings. */ + ~STM32_TIM_DIER_IRQ_MASK; +#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 || STM32_PWM_USE_TIM20 +#if STM32_PWM_USE_ADVANCED + pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE; +#else + pwmp->tim->BDTR = STM32_TIM_BDTR_MOE; +#endif +#endif + /* Timer configured and started.*/ + pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | + STM32_TIM_CR1_CEN; +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_stop(PWMDriver *pwmp) { + + /* If in ready state then disables the PWM clock.*/ + if (pwmp->state == PWM_READY) { + pwmp->tim->CR1 = 0; /* Timer disabled. */ + pwmp->tim->DIER = 0; /* All IRQs disabled. */ + pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ +#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 || STM32_PWM_USE_TIM20 + pwmp->tim->BDTR = 0; +#endif + +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); +#endif + rccDisableTIM1(); + } +#endif + +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM2_NUMBER); +#endif + rccDisableTIM2(); + } +#endif + +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM3_NUMBER); +#endif + rccDisableTIM3(); + } +#endif + +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM4_NUMBER); +#endif + rccDisableTIM4(); + } +#endif + +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM5_NUMBER); +#endif + rccDisableTIM5(); + } +#endif + +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); +#endif + rccDisableTIM8(); + } +#endif + +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + rccDisableTIM9(); + } +#endif + +#if STM32_PWM_USE_TIM10 + if (&PWMD10 == pwmp) { + rccDisableTIM10(); + } +#endif + +#if STM32_PWM_USE_TIM11 + if (&PWMD11 == pwmp) { + rccDisableTIM11(); + } +#endif + +#if STM32_PWM_USE_TIM12 + if (&PWMD12 == pwmp) { + rccDisableTIM12(); + } +#endif + +#if STM32_PWM_USE_TIM13 + if (&PWMD13 == pwmp) { + rccDisableTIM13(); + } +#endif + +#if STM32_PWM_USE_TIM14 + if (&PWMD14 == pwmp) { + rccDisableTIM14(); + } +#endif + +#if STM32_PWM_USE_TIM15 + if (&PWMD15 == pwmp) { + rccDisableTIM15(); + } +#endif + +#if STM32_PWM_USE_TIM16 + if (&PWMD16 == pwmp) { + rccDisableTIM16(); + } +#endif + +#if STM32_PWM_USE_TIM17 + if (&PWMD17 == pwmp) { + rccDisableTIM17(); + } +#endif + +#if STM32_PWM_USE_TIM20 + if (&PWMD20 == pwmp) { + rccDisableTIM20(); + } +#endif + +#if STM32_PWM_USE_TIM21 + if (&PWMD21 == pwmp) { + rccDisableTIM21(); + } +#endif + +#if STM32_PWM_USE_TIM22 + if (&PWMD22 == pwmp) { + rccDisableTIM22(); + } +#endif + } +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note The function has effect at the next cycle start. + * @note Channel notification is not enabled. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @notapi + */ +void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + + /* Changing channel duty cycle on the fly.*/ +#if STM32_TIM_MAX_CHANNELS <= 4 + pwmp->tim->CCR[channel] = width; +#else + if (channel < 4) + pwmp->tim->CCR[channel] = width; + else + pwmp->tim->CCXR[channel - 4] = width; +#endif +} + +/** + * @brief Disables a PWM channel and its notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + +#if STM32_TIM_MAX_CHANNELS <= 4 + pwmp->tim->CCR[channel] = 0; + pwmp->tim->DIER &= ~(2 << channel); +#else + if (channel < 4) { + pwmp->tim->CCR[channel] = 0; + pwmp->tim->DIER &= ~(2 << channel); + } + else + pwmp->tim->CCXR[channel - 4] = 0; +#endif +} + +/** + * @brief Enables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) { + uint32_t dier = pwmp->tim->DIER; + + /* If the IRQ is not already enabled care must be taken to clear it, + it is probably already pending because the timer is running.*/ + if ((dier & STM32_TIM_DIER_UIE) == 0) { + pwmp->tim->SR = ~STM32_TIM_SR_UIF; + pwmp->tim->DIER = dier | STM32_TIM_DIER_UIE; + } +} + +/** + * @brief Disables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { + + pwmp->tim->DIER &= ~STM32_TIM_DIER_UIE; +} + +/** + * @brief Enables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + uint32_t dier = pwmp->tim->DIER; + +#if STM32_TIM_MAX_CHANNELS > 4 + /* Channels 4 and 5 do not support callbacks.*/ + osalDbgAssert(channel < 4, "callback not supported"); +#endif + + /* If the IRQ is not already enabled care must be taken to clear it, + it is probably already pending because the timer is running.*/ + if ((dier & (2 << channel)) == 0) { + pwmp->tim->SR = ~(2 << channel); + pwmp->tim->DIER = dier | (2 << channel); + } +} + +/** + * @brief Disables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + + pwmp->tim->DIER &= ~(2 << channel); +} + +/** + * @brief Common TIM2...TIM5,TIM9 IRQ handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_serve_interrupt(PWMDriver *pwmp) { + uint32_t sr; + + sr = pwmp->tim->SR; + sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + pwmp->tim->SR = ~sr; + if (((sr & STM32_TIM_SR_CC1IF) != 0) && + (pwmp->config->channels[0].callback != NULL)) + pwmp->config->channels[0].callback(pwmp); + if (((sr & STM32_TIM_SR_CC2IF) != 0) && + (pwmp->config->channels[1].callback != NULL)) + pwmp->config->channels[1].callback(pwmp); + if (((sr & STM32_TIM_SR_CC3IF) != 0) && + (pwmp->config->channels[2].callback != NULL)) + pwmp->config->channels[2].callback(pwmp); + if (((sr & STM32_TIM_SR_CC4IF) != 0) && + (pwmp->config->channels[3].callback != NULL)) + pwmp->config->channels[3].callback(pwmp); + if (((sr & STM32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL)) + pwmp->config->callback(pwmp); +} + +#endif /* HAL_USE_PWM */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h index b244e8b4ed..a1fce8ea60 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h @@ -1,1034 +1,1034 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_pwm_lld.h - * @brief STM32 PWM subsystem low level driver header. - * - * @addtogroup PWM - * @{ - */ - -#ifndef HAL_PWM_LLD_H -#define HAL_PWM_LLD_H - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Number of PWM channels per PWM driver. - */ -#define PWM_CHANNELS STM32_TIM_MAX_CHANNELS - -/** - * @name STM32-specific PWM complementary output mode macros - * @{ - */ -/** - * @brief Complementary output modes mask. - * @note This is an STM32-specific setting. - */ -#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0 - -/** - * @brief Complementary output not driven. - * @note This is an STM32-specific setting. - */ -#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00 - -/** - * @brief Complementary output, active is logic level one. - * @note This is an STM32-specific setting. - * @note This setting is only available if the configuration option - * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced - * timers TIM1 and TIM8. - */ -#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10 - -/** - * @brief Complementary output, active is logic level zero. - * @note This is an STM32-specific setting. - * @note This setting is only available if the configuration option - * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced - * timers TIM1 and TIM8. - */ -#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief If advanced timer features switch. - * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are - * enabled. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__) -#define STM32_PWM_USE_ADVANCED FALSE -#endif - -/** - * @brief PWMD1 driver enable switch. - * @details If set to @p TRUE the support for PWMD1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM1 FALSE -#endif - -/** - * @brief PWMD2 driver enable switch. - * @details If set to @p TRUE the support for PWMD2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM2 FALSE -#endif - -/** - * @brief PWMD3 driver enable switch. - * @details If set to @p TRUE the support for PWMD3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM3 FALSE -#endif - -/** - * @brief PWMD4 driver enable switch. - * @details If set to @p TRUE the support for PWMD4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM4 FALSE -#endif - -/** - * @brief PWMD5 driver enable switch. - * @details If set to @p TRUE the support for PWMD5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM5 FALSE -#endif - -/** - * @brief PWMD8 driver enable switch. - * @details If set to @p TRUE the support for PWMD8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM8 FALSE -#endif - -/** - * @brief PWMD9 driver enable switch. - * @details If set to @p TRUE the support for PWMD9 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM9 FALSE -#endif - -/** - * @brief PWMD10 driver enable switch. - * @details If set to @p TRUE the support for PWMD10 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM10) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM10 FALSE -#endif - -/** - * @brief PWMD11 driver enable switch. - * @details If set to @p TRUE the support for PWMD11 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM11) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM11 FALSE -#endif - -/** - * @brief PWMD12 driver enable switch. - * @details If set to @p TRUE the support for PWMD12 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM12) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM12 FALSE -#endif - -/** - * @brief PWMD13 driver enable switch. - * @details If set to @p TRUE the support for PWMD13 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM13) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM13 FALSE -#endif - -/** - * @brief PWMD14 driver enable switch. - * @details If set to @p TRUE the support for PWMD14 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM14) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM14 FALSE -#endif - -/** - * @brief PWMD15 driver enable switch. - * @details If set to @p TRUE the support for PWMD15 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM15) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM15 FALSE -#endif - -/** - * @brief PWMD16 driver enable switch. - * @details If set to @p TRUE the support for PWMD16 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM16) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM16 FALSE -#endif - -/** - * @brief PWMD17 driver enable switch. - * @details If set to @p TRUE the support for PWMD17 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM17) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM17 FALSE -#endif - -/** - * @brief PWMD20 driver enable switch. - * @details If set to @p TRUE the support for PWMD20 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM20) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM20 FALSE -#endif - -/** - * @brief PWMD21 driver enable switch. - * @details If set to @p TRUE the support for PWMD21 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM21) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM21 FALSE -#endif - -/** - * @brief PWMD22 driver enable switch. - * @details If set to @p TRUE the support for PWMD22 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_PWM_USE_TIM22) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM22 FALSE -#endif - -/** - * @brief PWMD1 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD2 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD3 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD4 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD5 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD8 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD9 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD10 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM10_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD11 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM11_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD12 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM12_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD13 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM13_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD14 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM14_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD15 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM15_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD16 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM16_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM16_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD17 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM17_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM17_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD20 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM20_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM20_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD21 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM21_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD22 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM22_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Configuration checks. */ -/*===========================================================================*/ - -#if !defined(STM32_HAS_TIM1) -#define STM32_HAS_TIM1 FALSE -#endif - -#if !defined(STM32_HAS_TIM2) -#define STM32_HAS_TIM2 FALSE -#endif - -#if !defined(STM32_HAS_TIM3) -#define STM32_HAS_TIM3 FALSE -#endif - -#if !defined(STM32_HAS_TIM4) -#define STM32_HAS_TIM4 FALSE -#endif - -#if !defined(STM32_HAS_TIM5) -#define STM32_HAS_TIM5 FALSE -#endif - -#if !defined(STM32_HAS_TIM8) -#define STM32_HAS_TIM8 FALSE -#endif - -#if !defined(STM32_HAS_TIM9) -#define STM32_HAS_TIM9 FALSE -#endif - -#if !defined(STM32_HAS_TIM10) -#define STM32_HAS_TIM10 FALSE -#endif - -#if !defined(STM32_HAS_TIM11) -#define STM32_HAS_TIM11 FALSE -#endif - -#if !defined(STM32_HAS_TIM12) -#define STM32_HAS_TIM12 FALSE -#endif - -#if !defined(STM32_HAS_TIM13) -#define STM32_HAS_TIM13 FALSE -#endif - -#if !defined(STM32_HAS_TIM14) -#define STM32_HAS_TIM14 FALSE -#endif - -#if !defined(STM32_HAS_TIM15) -#define STM32_HAS_TIM15 FALSE -#endif - -#if !defined(STM32_HAS_TIM16) -#define STM32_HAS_TIM16 FALSE -#endif - -#if !defined(STM32_HAS_TIM17) -#define STM32_HAS_TIM17 FALSE -#endif - -#if !defined(STM32_HAS_TIM20) -#define STM32_HAS_TIM20 FALSE -#endif - -#if !defined(STM32_HAS_TIM21) -#define STM32_HAS_TIM21 FALSE -#endif - -#if !defined(STM32_HAS_TIM22) -#define STM32_HAS_TIM22 FALSE -#endif - -#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM10 && !STM32_HAS_TIM10 -#error "TIM10 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM11 && !STM32_HAS_TIM11 -#error "TIM11 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM12 && !STM32_HAS_TIM12 -#error "TIM12 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM13 && !STM32_HAS_TIM13 -#error "TIM13 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM14 && !STM32_HAS_TIM14 -#error "TIM14 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM15 && !STM32_HAS_TIM15 -#error "TIM15 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM16 && !STM32_HAS_TIM16 -#error "TIM16 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM17 && !STM32_HAS_TIM17 -#error "TIM17 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM20 && !STM32_HAS_TIM20 -#error "TIM20 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM21 && !STM32_HAS_TIM21 -#error "TIM21 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM22 && !STM32_HAS_TIM22 -#error "TIM22 not present in the selected device" -#endif - -#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \ - !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \ - !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \ - !STM32_PWM_USE_TIM9 && !STM32_PWM_USE_TIM10 && \ - !STM32_PWM_USE_TIM11 && !STM32_PWM_USE_TIM12 && \ - !STM32_PWM_USE_TIM13 && !STM32_PWM_USE_TIM14 && \ - !STM32_PWM_USE_TIM15 && !STM32_PWM_USE_TIM16 && \ - !STM32_PWM_USE_TIM17 && !STM32_PWM_USE_TIM20 && \ - !STM32_PWM_USE_TIM21 && !STM32_PWM_USE_TIM22 -#error "PWM driver activated but no TIM peripheral assigned" -#endif - -#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && \ - !STM32_PWM_USE_TIM20 -#error "advanced mode selected but no advanced timer assigned" -#endif - -/* Checks on allocation of TIMx units.*/ -#if STM32_PWM_USE_TIM1 -#if defined(STM32_TIM1_IS_USED) -#error "PWMD1 requires TIM1 but the timer is already used" -#else -#define STM32_TIM1_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM2 -#if defined(STM32_TIM2_IS_USED) -#error "PWMD2 requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM3 -#if defined(STM32_TIM3_IS_USED) -#error "PWMD3 requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM4 -#if defined(STM32_TIM4_IS_USED) -#error "PWMD4 requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM5 -#if defined(STM32_TIM5_IS_USED) -#error "PWMD5 requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM8 -#if defined(STM32_TIM8_IS_USED) -#error "PWMD8 requires TIM8 but the timer is already used" -#else -#define STM32_TIM8_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM9 -#if defined(STM32_TIM9_IS_USED) -#error "PWMD9 requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM10 -#if defined(STM32_TIM10_IS_USED) -#error "PWMD10 requires TIM10 but the timer is already used" -#else -#define STM32_TIM10_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM11 -#if defined(STM32_TIM11_IS_USED) -#error "PWMD11 requires TIM11 but the timer is already used" -#else -#define STM32_TIM11_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM12 -#if defined(STM32_TIM12_IS_USED) -#error "PWMD12 requires TIM12 but the timer is already used" -#else -#define STM32_TIM12_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM13 -#if defined(STM32_TIM13_IS_USED) -#error "PWMD13 requires TIM13 but the timer is already used" -#else -#define STM32_TIM13_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM14 -#if defined(STM32_TIM14_IS_USED) -#error "PWMD14 requires TIM14 but the timer is already used" -#else -#define STM32_TIM14_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM15 -#if defined(STM32_TIM15_IS_USED) -#error "PWMD15 requires TIM15 but the timer is already used" -#else -#define STM32_TIM15_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM16 -#if defined(STM32_TIM16_IS_USED) -#error "PWMD16 requires TIM16 but the timer is already used" -#else -#define STM32_TIM16_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM17 -#if defined(STM32_TIM17_IS_USED) -#error "PWMD17 requires TIM17 but the timer is already used" -#else -#define STM32_TIM17_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM20 -#if defined(STM32_TIM20_IS_USED) -#error "PWMD20 requires TIM20 but the timer is already used" -#else -#define STM32_TIM20_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM21 -#if defined(STM32_TIM21_IS_USED) -#error "PWMD21 requires TIM21 but the timer is already used" -#else -#define STM32_TIM21_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM22 -#if defined(STM32_TIM22_IS_USED) -#error "PWMD22 requires TIM22 but the timer is already used" -#else -#define STM32_TIM22_IS_USED -#endif -#endif - -/* IRQ priority checks.*/ -#if STM32_PWM_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_PWM_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_PWM_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_PWM_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_PWM_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_PWM_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_PWM_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -#if STM32_PWM_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM10_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM10" -#endif - -#if STM32_PWM_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM11_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM11" -#endif - -#if STM32_PWM_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM12" -#endif - -#if STM32_PWM_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM13_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM13" -#endif - -#if STM32_PWM_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM14_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM14" -#endif - -#if STM32_PWM_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM15_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM15" -#endif - -#if STM32_PWM_USE_TIM16 && !defined(STM32_TIM16_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM16_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM16" -#endif - -#if STM32_PWM_USE_TIM17 && !defined(STM32_TIM17_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM17_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM17" -#endif - -#if STM32_PWM_USE_TIM20 && !defined(STM32_TIM20_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM20_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM20" -#endif - -#if STM32_PWM_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM21_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM21" -#endif - -#if STM32_PWM_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM22_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM22" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a PWM mode. - */ -typedef uint32_t pwmmode_t; - -/** - * @brief Type of a PWM channel. - */ -typedef uint8_t pwmchannel_t; - -/** - * @brief Type of a channels mask. - */ -typedef uint32_t pwmchnmsk_t; - -/** - * @brief Type of a PWM counter. - */ -typedef uint32_t pwmcnt_t; - -/** - * @brief Type of a PWM driver channel configuration structure. - */ -typedef struct { - /** - * @brief Channel active logic level. - */ - pwmmode_t mode; - /** - * @brief Channel callback pointer. - * @note This callback is invoked on the channel compare event. If set to - * @p NULL then the callback is disabled. - */ - pwmcallback_t callback; - /* End of the mandatory fields.*/ -} PWMChannelConfig; - -/** - * @brief Type of a PWM driver configuration structure. - */ -typedef struct { - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - uint32_t frequency; - /** - * @brief PWM period in ticks. - * @note The low level can use assertions in order to catch invalid - * period specifications. - */ - pwmcnt_t period; - /** - * @brief Periodic callback pointer. - * @note This callback is invoked on PWM counter reset. If set to - * @p NULL then the callback is disabled. - */ - pwmcallback_t callback; - /** - * @brief Channels configurations. - */ - PWMChannelConfig channels[PWM_CHANNELS]; - /* End of the mandatory fields.*/ - /** - * @brief TIM CR2 register initialization data. - * @note The value of this field should normally be equal to zero. - */ - uint32_t cr2; -#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__) - /** - * @brief TIM BDTR (break & dead-time) register initialization data. - * @note The value of this field should normally be equal to zero. - */ \ - uint32_t bdtr; -#endif - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} PWMConfig; - -/** - * @brief Structure representing a PWM driver. - */ -struct PWMDriver { - /** - * @brief Driver state. - */ - pwmstate_t state; - /** - * @brief Current driver configuration data. - */ - const PWMConfig *config; - /** - * @brief Current PWM period in ticks. - */ - pwmcnt_t period; - /** - * @brief Mask of the enabled channels. - */ - pwmchnmsk_t enabled; - /** - * @brief Number of channels in this instance. - */ - pwmchannel_t channels; -#if defined(PWM_DRIVER_EXT_FIELDS) - PWM_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the period the PWM peripheral. - * @details This function changes the period of a PWM unit that has already - * been activated using @p pwmStart(). - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The PWM unit period is changed to the new value. - * @note The function has effect at the next cycle start. - * @note If a period is specified that is shorter than the pulse width - * programmed in one of the channels then the behavior is not - * guaranteed. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] period new cycle time in ticks - * - * @notapi - */ -#define pwm_lld_change_period(pwmp, period) \ - ((pwmp)->tim->ARR = ((period) - 1)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__) -extern PWMDriver PWMD1; -#endif - -#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__) -extern PWMDriver PWMD2; -#endif - -#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__) -extern PWMDriver PWMD3; -#endif - -#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__) -extern PWMDriver PWMD4; -#endif - -#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__) -extern PWMDriver PWMD5; -#endif - -#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__) -extern PWMDriver PWMD8; -#endif - -#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__) -extern PWMDriver PWMD9; -#endif - -#if STM32_PWM_USE_TIM10 && !defined(__DOXYGEN__) -extern PWMDriver PWMD10; -#endif - -#if STM32_PWM_USE_TIM11 && !defined(__DOXYGEN__) -extern PWMDriver PWMD11; -#endif - -#if STM32_PWM_USE_TIM12 && !defined(__DOXYGEN__) -extern PWMDriver PWMD12; -#endif - -#if STM32_PWM_USE_TIM13 && !defined(__DOXYGEN__) -extern PWMDriver PWMD13; -#endif - -#if STM32_PWM_USE_TIM14 && !defined(__DOXYGEN__) -extern PWMDriver PWMD14; -#endif - -#if STM32_PWM_USE_TIM15 && !defined(__DOXYGEN__) -extern PWMDriver PWMD15; -#endif - -#if STM32_PWM_USE_TIM16 && !defined(__DOXYGEN__) -extern PWMDriver PWMD16; -#endif - -#if STM32_PWM_USE_TIM17 && !defined(__DOXYGEN__) -extern PWMDriver PWMD17; -#endif - -#if STM32_PWM_USE_TIM20 && !defined(__DOXYGEN__) -extern PWMDriver PWMD20; -#endif - -#if STM32_PWM_USE_TIM21 && !defined(__DOXYGEN__) -extern PWMDriver PWMD21; -#endif - -#if STM32_PWM_USE_TIM22 && !defined(__DOXYGEN__) -extern PWMDriver PWMD22; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void pwm_lld_init(void); - void pwm_lld_start(PWMDriver *pwmp); - void pwm_lld_stop(PWMDriver *pwmp); - void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width); - void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); - void pwm_lld_enable_periodic_notification(PWMDriver *pwmp); - void pwm_lld_disable_periodic_notification(PWMDriver *pwmp); - void pwm_lld_enable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel); - void pwm_lld_disable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel); - void pwm_lld_serve_interrupt(PWMDriver *pwmp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PWM */ - -#endif /* HAL_PWM_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_pwm_lld.h + * @brief STM32 PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#ifndef HAL_PWM_LLD_H +#define HAL_PWM_LLD_H + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Number of PWM channels per PWM driver. + */ +#define PWM_CHANNELS STM32_TIM_MAX_CHANNELS + +/** + * @name STM32-specific PWM complementary output mode macros + * @{ + */ +/** + * @brief Complementary output modes mask. + * @note This is an STM32-specific setting. + */ +#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0 + +/** + * @brief Complementary output not driven. + * @note This is an STM32-specific setting. + */ +#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00 + +/** + * @brief Complementary output, active is logic level one. + * @note This is an STM32-specific setting. + * @note This setting is only available if the configuration option + * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced + * timers TIM1 and TIM8. + */ +#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10 + +/** + * @brief Complementary output, active is logic level zero. + * @note This is an STM32-specific setting. + * @note This setting is only available if the configuration option + * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced + * timers TIM1 and TIM8. + */ +#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief If advanced timer features switch. + * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are + * enabled. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__) +#define STM32_PWM_USE_ADVANCED FALSE +#endif + +/** + * @brief PWMD1 driver enable switch. + * @details If set to @p TRUE the support for PWMD1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM1 FALSE +#endif + +/** + * @brief PWMD2 driver enable switch. + * @details If set to @p TRUE the support for PWMD2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM2 FALSE +#endif + +/** + * @brief PWMD3 driver enable switch. + * @details If set to @p TRUE the support for PWMD3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM3 FALSE +#endif + +/** + * @brief PWMD4 driver enable switch. + * @details If set to @p TRUE the support for PWMD4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM4 FALSE +#endif + +/** + * @brief PWMD5 driver enable switch. + * @details If set to @p TRUE the support for PWMD5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM5 FALSE +#endif + +/** + * @brief PWMD8 driver enable switch. + * @details If set to @p TRUE the support for PWMD8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM8 FALSE +#endif + +/** + * @brief PWMD9 driver enable switch. + * @details If set to @p TRUE the support for PWMD9 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM9 FALSE +#endif + +/** + * @brief PWMD10 driver enable switch. + * @details If set to @p TRUE the support for PWMD10 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM10) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM10 FALSE +#endif + +/** + * @brief PWMD11 driver enable switch. + * @details If set to @p TRUE the support for PWMD11 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM11) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM11 FALSE +#endif + +/** + * @brief PWMD12 driver enable switch. + * @details If set to @p TRUE the support for PWMD12 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM12) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM12 FALSE +#endif + +/** + * @brief PWMD13 driver enable switch. + * @details If set to @p TRUE the support for PWMD13 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM13) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM13 FALSE +#endif + +/** + * @brief PWMD14 driver enable switch. + * @details If set to @p TRUE the support for PWMD14 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM14) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM14 FALSE +#endif + +/** + * @brief PWMD15 driver enable switch. + * @details If set to @p TRUE the support for PWMD15 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM15) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM15 FALSE +#endif + +/** + * @brief PWMD16 driver enable switch. + * @details If set to @p TRUE the support for PWMD16 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM16) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM16 FALSE +#endif + +/** + * @brief PWMD17 driver enable switch. + * @details If set to @p TRUE the support for PWMD17 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM17) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM17 FALSE +#endif + +/** + * @brief PWMD20 driver enable switch. + * @details If set to @p TRUE the support for PWMD20 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM20) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM20 FALSE +#endif + +/** + * @brief PWMD21 driver enable switch. + * @details If set to @p TRUE the support for PWMD21 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM21) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM21 FALSE +#endif + +/** + * @brief PWMD22 driver enable switch. + * @details If set to @p TRUE the support for PWMD22 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_PWM_USE_TIM22) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM22 FALSE +#endif + +/** + * @brief PWMD1 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD2 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD3 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD4 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD5 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD8 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD9 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD10 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM10_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD11 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM11_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD12 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM12_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD13 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM13_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD14 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM14_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD15 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM15_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD16 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM16_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM16_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD17 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM17_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM17_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD20 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM20_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM20_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD21 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM21_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD22 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM22_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Configuration checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_TIM1) +#define STM32_HAS_TIM1 FALSE +#endif + +#if !defined(STM32_HAS_TIM2) +#define STM32_HAS_TIM2 FALSE +#endif + +#if !defined(STM32_HAS_TIM3) +#define STM32_HAS_TIM3 FALSE +#endif + +#if !defined(STM32_HAS_TIM4) +#define STM32_HAS_TIM4 FALSE +#endif + +#if !defined(STM32_HAS_TIM5) +#define STM32_HAS_TIM5 FALSE +#endif + +#if !defined(STM32_HAS_TIM8) +#define STM32_HAS_TIM8 FALSE +#endif + +#if !defined(STM32_HAS_TIM9) +#define STM32_HAS_TIM9 FALSE +#endif + +#if !defined(STM32_HAS_TIM10) +#define STM32_HAS_TIM10 FALSE +#endif + +#if !defined(STM32_HAS_TIM11) +#define STM32_HAS_TIM11 FALSE +#endif + +#if !defined(STM32_HAS_TIM12) +#define STM32_HAS_TIM12 FALSE +#endif + +#if !defined(STM32_HAS_TIM13) +#define STM32_HAS_TIM13 FALSE +#endif + +#if !defined(STM32_HAS_TIM14) +#define STM32_HAS_TIM14 FALSE +#endif + +#if !defined(STM32_HAS_TIM15) +#define STM32_HAS_TIM15 FALSE +#endif + +#if !defined(STM32_HAS_TIM16) +#define STM32_HAS_TIM16 FALSE +#endif + +#if !defined(STM32_HAS_TIM17) +#define STM32_HAS_TIM17 FALSE +#endif + +#if !defined(STM32_HAS_TIM20) +#define STM32_HAS_TIM20 FALSE +#endif + +#if !defined(STM32_HAS_TIM21) +#define STM32_HAS_TIM21 FALSE +#endif + +#if !defined(STM32_HAS_TIM22) +#define STM32_HAS_TIM22 FALSE +#endif + +#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM10 && !STM32_HAS_TIM10 +#error "TIM10 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM11 && !STM32_HAS_TIM11 +#error "TIM11 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM12 && !STM32_HAS_TIM12 +#error "TIM12 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM13 && !STM32_HAS_TIM13 +#error "TIM13 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM14 && !STM32_HAS_TIM14 +#error "TIM14 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM15 && !STM32_HAS_TIM15 +#error "TIM15 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM16 && !STM32_HAS_TIM16 +#error "TIM16 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM17 && !STM32_HAS_TIM17 +#error "TIM17 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM20 && !STM32_HAS_TIM20 +#error "TIM20 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM21 && !STM32_HAS_TIM21 +#error "TIM21 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM22 && !STM32_HAS_TIM22 +#error "TIM22 not present in the selected device" +#endif + +#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \ + !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \ + !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \ + !STM32_PWM_USE_TIM9 && !STM32_PWM_USE_TIM10 && \ + !STM32_PWM_USE_TIM11 && !STM32_PWM_USE_TIM12 && \ + !STM32_PWM_USE_TIM13 && !STM32_PWM_USE_TIM14 && \ + !STM32_PWM_USE_TIM15 && !STM32_PWM_USE_TIM16 && \ + !STM32_PWM_USE_TIM17 && !STM32_PWM_USE_TIM20 && \ + !STM32_PWM_USE_TIM21 && !STM32_PWM_USE_TIM22 +#error "PWM driver activated but no TIM peripheral assigned" +#endif + +#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && \ + !STM32_PWM_USE_TIM20 +#error "advanced mode selected but no advanced timer assigned" +#endif + +/* Checks on allocation of TIMx units.*/ +#if STM32_PWM_USE_TIM1 +#if defined(STM32_TIM1_IS_USED) +#error "PWMD1 requires TIM1 but the timer is already used" +#else +#define STM32_TIM1_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM2 +#if defined(STM32_TIM2_IS_USED) +#error "PWMD2 requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM3 +#if defined(STM32_TIM3_IS_USED) +#error "PWMD3 requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM4 +#if defined(STM32_TIM4_IS_USED) +#error "PWMD4 requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM5 +#if defined(STM32_TIM5_IS_USED) +#error "PWMD5 requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM8 +#if defined(STM32_TIM8_IS_USED) +#error "PWMD8 requires TIM8 but the timer is already used" +#else +#define STM32_TIM8_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM9 +#if defined(STM32_TIM9_IS_USED) +#error "PWMD9 requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM10 +#if defined(STM32_TIM10_IS_USED) +#error "PWMD10 requires TIM10 but the timer is already used" +#else +#define STM32_TIM10_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM11 +#if defined(STM32_TIM11_IS_USED) +#error "PWMD11 requires TIM11 but the timer is already used" +#else +#define STM32_TIM11_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM12 +#if defined(STM32_TIM12_IS_USED) +#error "PWMD12 requires TIM12 but the timer is already used" +#else +#define STM32_TIM12_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM13 +#if defined(STM32_TIM13_IS_USED) +#error "PWMD13 requires TIM13 but the timer is already used" +#else +#define STM32_TIM13_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM14 +#if defined(STM32_TIM14_IS_USED) +#error "PWMD14 requires TIM14 but the timer is already used" +#else +#define STM32_TIM14_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM15 +#if defined(STM32_TIM15_IS_USED) +#error "PWMD15 requires TIM15 but the timer is already used" +#else +#define STM32_TIM15_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM16 +#if defined(STM32_TIM16_IS_USED) +#error "PWMD16 requires TIM16 but the timer is already used" +#else +#define STM32_TIM16_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM17 +#if defined(STM32_TIM17_IS_USED) +#error "PWMD17 requires TIM17 but the timer is already used" +#else +#define STM32_TIM17_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM20 +#if defined(STM32_TIM20_IS_USED) +#error "PWMD20 requires TIM20 but the timer is already used" +#else +#define STM32_TIM20_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM21 +#if defined(STM32_TIM21_IS_USED) +#error "PWMD21 requires TIM21 but the timer is already used" +#else +#define STM32_TIM21_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM22 +#if defined(STM32_TIM22_IS_USED) +#error "PWMD22 requires TIM22 but the timer is already used" +#else +#define STM32_TIM22_IS_USED +#endif +#endif + +/* IRQ priority checks.*/ +#if STM32_PWM_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_PWM_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_PWM_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_PWM_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_PWM_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_PWM_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_PWM_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +#if STM32_PWM_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM10_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM10" +#endif + +#if STM32_PWM_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM11_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM11" +#endif + +#if STM32_PWM_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM12" +#endif + +#if STM32_PWM_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM13_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM13" +#endif + +#if STM32_PWM_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM14_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM14" +#endif + +#if STM32_PWM_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM15_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM15" +#endif + +#if STM32_PWM_USE_TIM16 && !defined(STM32_TIM16_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM16_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM16" +#endif + +#if STM32_PWM_USE_TIM17 && !defined(STM32_TIM17_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM17_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM17" +#endif + +#if STM32_PWM_USE_TIM20 && !defined(STM32_TIM20_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM20_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM20" +#endif + +#if STM32_PWM_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM21_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM21" +#endif + +#if STM32_PWM_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM22_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM22" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a PWM mode. + */ +typedef uint32_t pwmmode_t; + +/** + * @brief Type of a PWM channel. + */ +typedef uint8_t pwmchannel_t; + +/** + * @brief Type of a channels mask. + */ +typedef uint32_t pwmchnmsk_t; + +/** + * @brief Type of a PWM counter. + */ +typedef uint32_t pwmcnt_t; + +/** + * @brief Type of a PWM driver channel configuration structure. + */ +typedef struct { + /** + * @brief Channel active logic level. + */ + pwmmode_t mode; + /** + * @brief Channel callback pointer. + * @note This callback is invoked on the channel compare event. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /* End of the mandatory fields.*/ +} PWMChannelConfig; + +/** + * @brief Type of a PWM driver configuration structure. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + uint32_t frequency; + /** + * @brief PWM period in ticks. + * @note The low level can use assertions in order to catch invalid + * period specifications. + */ + pwmcnt_t period; + /** + * @brief Periodic callback pointer. + * @note This callback is invoked on PWM counter reset. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /** + * @brief Channels configurations. + */ + PWMChannelConfig channels[PWM_CHANNELS]; + /* End of the mandatory fields.*/ + /** + * @brief TIM CR2 register initialization data. + * @note The value of this field should normally be equal to zero. + */ + uint32_t cr2; +#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__) + /** + * @brief TIM BDTR (break & dead-time) register initialization data. + * @note The value of this field should normally be equal to zero. + */ \ + uint32_t bdtr; +#endif + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} PWMConfig; + +/** + * @brief Structure representing a PWM driver. + */ +struct PWMDriver { + /** + * @brief Driver state. + */ + pwmstate_t state; + /** + * @brief Current driver configuration data. + */ + const PWMConfig *config; + /** + * @brief Current PWM period in ticks. + */ + pwmcnt_t period; + /** + * @brief Mask of the enabled channels. + */ + pwmchnmsk_t enabled; + /** + * @brief Number of channels in this instance. + */ + pwmchannel_t channels; +#if defined(PWM_DRIVER_EXT_FIELDS) + PWM_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note The function has effect at the next cycle start. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @notapi + */ +#define pwm_lld_change_period(pwmp, period) \ + ((pwmp)->tim->ARR = ((period) - 1)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__) +extern PWMDriver PWMD1; +#endif + +#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__) +extern PWMDriver PWMD2; +#endif + +#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__) +extern PWMDriver PWMD3; +#endif + +#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__) +extern PWMDriver PWMD4; +#endif + +#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__) +extern PWMDriver PWMD5; +#endif + +#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__) +extern PWMDriver PWMD8; +#endif + +#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__) +extern PWMDriver PWMD9; +#endif + +#if STM32_PWM_USE_TIM10 && !defined(__DOXYGEN__) +extern PWMDriver PWMD10; +#endif + +#if STM32_PWM_USE_TIM11 && !defined(__DOXYGEN__) +extern PWMDriver PWMD11; +#endif + +#if STM32_PWM_USE_TIM12 && !defined(__DOXYGEN__) +extern PWMDriver PWMD12; +#endif + +#if STM32_PWM_USE_TIM13 && !defined(__DOXYGEN__) +extern PWMDriver PWMD13; +#endif + +#if STM32_PWM_USE_TIM14 && !defined(__DOXYGEN__) +extern PWMDriver PWMD14; +#endif + +#if STM32_PWM_USE_TIM15 && !defined(__DOXYGEN__) +extern PWMDriver PWMD15; +#endif + +#if STM32_PWM_USE_TIM16 && !defined(__DOXYGEN__) +extern PWMDriver PWMD16; +#endif + +#if STM32_PWM_USE_TIM17 && !defined(__DOXYGEN__) +extern PWMDriver PWMD17; +#endif + +#if STM32_PWM_USE_TIM20 && !defined(__DOXYGEN__) +extern PWMDriver PWMD20; +#endif + +#if STM32_PWM_USE_TIM21 && !defined(__DOXYGEN__) +extern PWMDriver PWMD21; +#endif + +#if STM32_PWM_USE_TIM22 && !defined(__DOXYGEN__) +extern PWMDriver PWMD22; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void pwm_lld_init(void); + void pwm_lld_start(PWMDriver *pwmp); + void pwm_lld_stop(PWMDriver *pwmp); + void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); + void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); + void pwm_lld_enable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_disable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); + void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); + void pwm_lld_serve_interrupt(PWMDriver *pwmp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM */ + +#endif /* HAL_PWM_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c index 4ffcc7aeb1..741361bb5b 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c @@ -1,492 +1,492 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_st_lld.c - * @brief ST Driver subsystem low level driver code. - * - * @addtogroup ST - * @{ - */ - -#include "hal.h" - -#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - -#if (OSAL_ST_RESOLUTION == 32) -#define ST_ARR_INIT 0xFFFFFFFFU -#else -#define ST_ARR_INIT 0x0000FFFFU -#endif - -#if STM32_ST_USE_TIMER == 2 - -#if !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM2_IS_32BITS -#error "TIM2 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM2_HANDLER -#define ST_NUMBER STM32_TIM2_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM2(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM2_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM2_STOP -#elif defined(STM32G0XX) -#define ST_ENABLE_STOP() DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM2_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM2 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP -#endif - -#elif STM32_ST_USE_TIMER == 3 - -#if !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM3_IS_32BITS -#error "TIM3 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM3_HANDLER -#define ST_NUMBER STM32_TIM3_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM3(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM3_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM3_STOP -#elif defined(STM32G0XX) -#define ST_ENABLE_STOP() DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM3 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP -#endif - -#elif STM32_ST_USE_TIMER == 4 - -#if !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM4_IS_32BITS -#error "TIM4 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM4_HANDLER -#define ST_NUMBER STM32_TIM4_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM4(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM4_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM4_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM4 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM4_STOP -#endif - -#elif STM32_ST_USE_TIMER == 5 - -#if !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM5_IS_32BITS -#error "TIM5 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM5_HANDLER -#define ST_NUMBER STM32_TIM5_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM5(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM5_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM5_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM5 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM5_STOP -#endif - -#elif STM32_ST_USE_TIMER == 9 - -#if !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM9_IS_32BITS -#error "TIM9 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM9_HANDLER -#define ST_NUMBER STM32_TIM9_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM9(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM9_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM9_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM9 -#else -#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM9_STOP -#endif - -#elif STM32_ST_USE_TIMER == 10 - -#if !STM32_HAS_TIM10 -#error "TIM10 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM10_IS_32BITS -#error "TIM10 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM10_HANDLER -#define ST_NUMBER STM32_TIM10_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM10(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM10_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM10_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM10 -#else -#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM10_STOP -#endif - -#elif STM32_ST_USE_TIMER == 11 - -#if !STM32_HAS_TIM11 -#error "TIM11 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM11_IS_32BITS -#error "TIM11 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM11_HANDLER -#define ST_NUMBER STM32_TIM11_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM11(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM11_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM11_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM11 -#else -#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM11_STOP -#endif - -#elif STM32_ST_USE_TIMER == 12 - -#if !STM32_HAS_TIM12 -#error "TIM12 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM12_IS_32BITS -#error "TIM12 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM12_HANDLER -#define ST_NUMBER STM32_TIM12_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM12(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM12_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM12_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM12 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM12_STOP -#endif - -#elif STM32_ST_USE_TIMER == 13 - -#if !STM32_HAS_TIM13 -#error "TIM13 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM13_IS_32BITS -#error "TIM13 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM13_HANDLER -#define ST_NUMBER STM32_TIM13_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM13(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM13_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM13_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM13 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM13_STOP -#endif - -#elif STM32_ST_USE_TIMER == 14 - -#if !STM32_HAS_TIM14 -#error "TIM14 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM14_IS_32BITS -#error "TIM14 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM14_HANDLER -#define ST_NUMBER STM32_TIM14_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM14(true) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM14_STOP -#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM14_STOP -#elif defined(STM32H7XX) -#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM14 -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM14_STOP -#endif - -#elif STM32_ST_USE_TIMER == 21 - -#if !STM32_HAS_TIM21 -#error "TIM21 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM21_IS_32BITS -#error "TIM21 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM21_HANDLER -#define ST_NUMBER STM32_TIM21_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM21(true) -#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP - -#elif STM32_ST_USE_TIMER == 22 - -#if !STM32_HAS_TIM22 -#error "TIM22 not present in the selected device" -#endif - -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM22_IS_32BITS -#error "TIM21 is not a 32bits timer" -#endif - -#define ST_HANDLER STM32_TIM22_HANDLER -#define ST_NUMBER STM32_TIM22_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM22(true) -#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP - -#else -#error "STM32_ST_USE_TIMER specifies an unsupported timer" -#endif - -#if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0 -#error "the selected ST frequency is not obtainable because integer rounding" -#endif - -#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF -#error "the selected ST frequency is not obtainable because TIM timer prescaler limits" -#endif - -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ - -#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - -#define ST_HANDLER SysTick_Handler - -#if defined(STM32_CORE_CK) -#define SYSTICK_CK STM32_CORE_CK -#else -#define SYSTICK_CK STM32_HCLK -#endif - -#if SYSTICK_CK % OSAL_ST_FREQUENCY != 0 -#error "the selected ST frequency is not obtainable because integer rounding" -#endif - -#if (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1 > 0xFFFFFF -#error "the selected ST frequency is not obtainable because SysTick timer counter limits" -#endif - -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if !defined(STM32_SYSTICK_SUPPRESS_ISR) -/** - * @brief Interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(ST_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - st_lld_serve_interrupt(); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ST driver initialization. - * - * @notapi - */ -void st_lld_init(void) { - -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - /* Free running counter mode.*/ - - /* Enabling timer clock.*/ - ST_ENABLE_CLOCK(); - - /* Enabling the stop mode during debug for this timer.*/ - ST_ENABLE_STOP(); - - /* Initializing the counter in free running mode.*/ - STM32_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1; - STM32_ST_TIM->ARR = ST_ARR_INIT; - STM32_ST_TIM->CCMR1 = 0; - STM32_ST_TIM->CCR[0] = 0; -#if ST_LLD_NUM_ALARMS > 1 - STM32_ST_TIM->CCR[1] = 0; -#endif -#if ST_LLD_NUM_ALARMS > 2 - STM32_ST_TIM->CCR[2] = 0; -#endif -#if ST_LLD_NUM_ALARMS > 3 - STM32_ST_TIM->CCR[3] = 0; -#endif - STM32_ST_TIM->DIER = 0; - STM32_ST_TIM->CR2 = 0; - STM32_ST_TIM->EGR = TIM_EGR_UG; - STM32_ST_TIM->CR1 = TIM_CR1_CEN; - -#if !defined(STM32_SYSTICK_SUPPRESS_ISR) - /* IRQ enabled.*/ - nvicEnableVector(ST_NUMBER, STM32_ST_IRQ_PRIORITY); -#endif -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ - -#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - /* Periodic systick mode, the Cortex-Mx internal systick timer is used - in this mode.*/ - SysTick->LOAD = (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1; - SysTick->VAL = 0; - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_ENABLE_Msk | - SysTick_CTRL_TICKINT_Msk; - - /* IRQ enabled.*/ - nvicSetSystemHandlerPriority(HANDLER_SYSTICK, STM32_ST_IRQ_PRIORITY); -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ -} - -/** - * @brief IRQ handling code. - */ -void st_lld_serve_interrupt(void) { -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - uint32_t sr; - stm32_tim_t *timp = STM32_ST_TIM; - - sr = timp->SR; - sr &= timp->DIER & STM32_TIM_DIER_IRQ_MASK; - timp->SR = ~sr; - - if ((sr & TIM_SR_CC1IF) != 0U) -#endif - { - osalSysLockFromISR(); - osalOsTimerHandlerI(); - osalSysUnlockFromISR(); - } -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING -#if ST_LLD_NUM_ALARMS > 1 - if ((sr & TIM_SR_CC2IF) != 0U) { - if (st_callbacks[1] != NULL) { - st_callbacks[1](1U); - } - } -#endif -#if ST_LLD_NUM_ALARMS > 2 - if ((sr & TIM_SR_CC3IF) != 0U) { - if (st_callbacks[2] != NULL) { - st_callbacks[2](2U); - } - } -#endif -#if ST_LLD_NUM_ALARMS > 3 - if ((sr & TIM_SR_CC4IF) != 0U) { - if (st_callbacks[3] != NULL) { - st_callbacks[3](3U); - } - } -#endif -#endif -} - -#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_st_lld.c + * @brief ST Driver subsystem low level driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + +#if (OSAL_ST_RESOLUTION == 32) +#define ST_ARR_INIT 0xFFFFFFFFU +#else +#define ST_ARR_INIT 0x0000FFFFU +#endif + +#if STM32_ST_USE_TIMER == 2 + +#if !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM2_IS_32BITS +#error "TIM2 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM2_HANDLER +#define ST_NUMBER STM32_TIM2_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM2(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM2_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM2_STOP +#elif defined(STM32G0XX) +#define ST_ENABLE_STOP() DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM2_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM2 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP +#endif + +#elif STM32_ST_USE_TIMER == 3 + +#if !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM3_IS_32BITS +#error "TIM3 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM3_HANDLER +#define ST_NUMBER STM32_TIM3_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM3(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM3_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM3_STOP +#elif defined(STM32G0XX) +#define ST_ENABLE_STOP() DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM3 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP +#endif + +#elif STM32_ST_USE_TIMER == 4 + +#if !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM4_IS_32BITS +#error "TIM4 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM4_HANDLER +#define ST_NUMBER STM32_TIM4_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM4(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM4_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM4_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM4 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM4_STOP +#endif + +#elif STM32_ST_USE_TIMER == 5 + +#if !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM5_IS_32BITS +#error "TIM5 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM5_HANDLER +#define ST_NUMBER STM32_TIM5_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM5(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM5_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM5_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM5 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM5_STOP +#endif + +#elif STM32_ST_USE_TIMER == 9 + +#if !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM9_IS_32BITS +#error "TIM9 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM9_HANDLER +#define ST_NUMBER STM32_TIM9_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM9(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM9_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM9_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM9 +#else +#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM9_STOP +#endif + +#elif STM32_ST_USE_TIMER == 10 + +#if !STM32_HAS_TIM10 +#error "TIM10 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM10_IS_32BITS +#error "TIM10 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM10_HANDLER +#define ST_NUMBER STM32_TIM10_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM10(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM10_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM10_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM10 +#else +#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM10_STOP +#endif + +#elif STM32_ST_USE_TIMER == 11 + +#if !STM32_HAS_TIM11 +#error "TIM11 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM11_IS_32BITS +#error "TIM11 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM11_HANDLER +#define ST_NUMBER STM32_TIM11_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM11(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM11_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM11_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM11 +#else +#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM11_STOP +#endif + +#elif STM32_ST_USE_TIMER == 12 + +#if !STM32_HAS_TIM12 +#error "TIM12 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM12_IS_32BITS +#error "TIM12 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM12_HANDLER +#define ST_NUMBER STM32_TIM12_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM12(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM12_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM12_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM12 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM12_STOP +#endif + +#elif STM32_ST_USE_TIMER == 13 + +#if !STM32_HAS_TIM13 +#error "TIM13 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM13_IS_32BITS +#error "TIM13 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM13_HANDLER +#define ST_NUMBER STM32_TIM13_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM13(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM13_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM13_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM13 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM13_STOP +#endif + +#elif STM32_ST_USE_TIMER == 14 + +#if !STM32_HAS_TIM14 +#error "TIM14 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM14_IS_32BITS +#error "TIM14 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM14_HANDLER +#define ST_NUMBER STM32_TIM14_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM14(true) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM14_STOP +#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM14_STOP +#elif defined(STM32H7XX) +#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM14 +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM14_STOP +#endif + +#elif STM32_ST_USE_TIMER == 21 + +#if !STM32_HAS_TIM21 +#error "TIM21 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM21_IS_32BITS +#error "TIM21 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM21_HANDLER +#define ST_NUMBER STM32_TIM21_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM21(true) +#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP + +#elif STM32_ST_USE_TIMER == 22 + +#if !STM32_HAS_TIM22 +#error "TIM22 not present in the selected device" +#endif + +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM22_IS_32BITS +#error "TIM21 is not a 32bits timer" +#endif + +#define ST_HANDLER STM32_TIM22_HANDLER +#define ST_NUMBER STM32_TIM22_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM22(true) +#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP + +#else +#error "STM32_ST_USE_TIMER specifies an unsupported timer" +#endif + +#if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0 +#error "the selected ST frequency is not obtainable because integer rounding" +#endif + +#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF +#error "the selected ST frequency is not obtainable because TIM timer prescaler limits" +#endif + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + +#define ST_HANDLER SysTick_Handler + +#if defined(STM32_CORE_CK) +#define SYSTICK_CK STM32_CORE_CK +#else +#define SYSTICK_CK STM32_HCLK +#endif + +#if SYSTICK_CK % OSAL_ST_FREQUENCY != 0 +#error "the selected ST frequency is not obtainable because integer rounding" +#endif + +#if (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1 > 0xFFFFFF +#error "the selected ST frequency is not obtainable because SysTick timer counter limits" +#endif + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if !defined(STM32_SYSTICK_SUPPRESS_ISR) +/** + * @brief Interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(ST_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + st_lld_serve_interrupt(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ST driver initialization. + * + * @notapi + */ +void st_lld_init(void) { + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + /* Free running counter mode.*/ + + /* Enabling timer clock.*/ + ST_ENABLE_CLOCK(); + + /* Enabling the stop mode during debug for this timer.*/ + ST_ENABLE_STOP(); + + /* Initializing the counter in free running mode.*/ + STM32_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1; + STM32_ST_TIM->ARR = ST_ARR_INIT; + STM32_ST_TIM->CCMR1 = 0; + STM32_ST_TIM->CCR[0] = 0; +#if ST_LLD_NUM_ALARMS > 1 + STM32_ST_TIM->CCR[1] = 0; +#endif +#if ST_LLD_NUM_ALARMS > 2 + STM32_ST_TIM->CCR[2] = 0; +#endif +#if ST_LLD_NUM_ALARMS > 3 + STM32_ST_TIM->CCR[3] = 0; +#endif + STM32_ST_TIM->DIER = 0; + STM32_ST_TIM->CR2 = 0; + STM32_ST_TIM->EGR = TIM_EGR_UG; + STM32_ST_TIM->CR1 = TIM_CR1_CEN; + +#if !defined(STM32_SYSTICK_SUPPRESS_ISR) + /* IRQ enabled.*/ + nvicEnableVector(ST_NUMBER, STM32_ST_IRQ_PRIORITY); +#endif +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + /* Periodic systick mode, the Cortex-Mx internal systick timer is used + in this mode.*/ + SysTick->LOAD = (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_ENABLE_Msk | + SysTick_CTRL_TICKINT_Msk; + + /* IRQ enabled.*/ + nvicSetSystemHandlerPriority(HANDLER_SYSTICK, STM32_ST_IRQ_PRIORITY); +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ +} + +/** + * @brief IRQ handling code. + */ +void st_lld_serve_interrupt(void) { +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + uint32_t sr; + stm32_tim_t *timp = STM32_ST_TIM; + + sr = timp->SR; + sr &= timp->DIER & STM32_TIM_DIER_IRQ_MASK; + timp->SR = ~sr; + + if ((sr & TIM_SR_CC1IF) != 0U) +#endif + { + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + } +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING +#if ST_LLD_NUM_ALARMS > 1 + if ((sr & TIM_SR_CC2IF) != 0U) { + if (st_callbacks[1] != NULL) { + st_callbacks[1](1U); + } + } +#endif +#if ST_LLD_NUM_ALARMS > 2 + if ((sr & TIM_SR_CC3IF) != 0U) { + if (st_callbacks[2] != NULL) { + st_callbacks[2](2U); + } + } +#endif +#if ST_LLD_NUM_ALARMS > 3 + if ((sr & TIM_SR_CC4IF) != 0U) { + if (st_callbacks[3] != NULL) { + st_callbacks[3](3U); + } + } +#endif +#endif +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h index f98e5b82be..01de7b7074 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h @@ -1,701 +1,701 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/hal_st_lld.h - * @brief ST Driver subsystem low level driver header. - * @details This header is designed to be include-able without having to - * include other files from the HAL. - * - * @addtogroup ST - * @{ - */ - -#ifndef HAL_ST_LLD_H -#define HAL_ST_LLD_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* Feature currently disabled.*/ -#define STM32_ST_ENFORCE_ALARMS 1 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SysTick timer IRQ priority. - */ -#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ST_IRQ_PRIORITY 8 -#endif - -/** - * @brief TIMx unit (by number) to be used for free running operations. - * @note You must select a 32 bits timer if a 32 bits @p systick_t type - * is required. - * @note Timers 2, 3, 4, 5, 21 and 22 are supported. - */ -#if !defined(STM32_ST_USE_TIMER) || defined(__DOXYGEN__) -#define STM32_ST_USE_TIMER 2 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* This has to go after transition to shared handlers is complete for all - platforms.*/ -#if !defined(STM32_HAS_TIM2) -#define STM32_HAS_TIM2 FALSE -#endif - -#if !defined(STM32_HAS_TIM3) -#define STM32_HAS_TIM3 FALSE -#endif - -#if !defined(STM32_HAS_TIM4) -#define STM32_HAS_TIM4 FALSE -#endif - -#if !defined(STM32_HAS_TIM5) -#define STM32_HAS_TIM5 FALSE -#endif - -#if !defined(STM32_HAS_TIM9) -#define STM32_HAS_TIM9 FALSE -#endif - -#if !defined(STM32_HAS_TIM10) -#define STM32_HAS_TIM10 FALSE -#endif - -#if !defined(STM32_HAS_TIM11) -#define STM32_HAS_TIM11 FALSE -#endif - -#if !defined(STM32_HAS_TIM12) -#define STM32_HAS_TIM12 FALSE -#endif - -#if !defined(STM32_HAS_TIM13) -#define STM32_HAS_TIM13 FALSE -#endif - -#if !defined(STM32_HAS_TIM14) -#define STM32_HAS_TIM14 FALSE -#endif - -#if !defined(STM32_HAS_TIM21) -#define STM32_HAS_TIM21 FALSE -#endif - -#if !defined(STM32_HAS_TIM22) -#define STM32_HAS_TIM22 FALSE -#endif -/**/ - -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - -#if STM32_ST_USE_TIMER == 2 - -#if defined(STM32_TIM2_IS_USED) -#error "ST requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif - -#if defined(STM32_TIM2_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM2 -#define ST_LLD_NUM_ALARMS STM32_TIM2_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 TRUE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 3 - -#if defined(STM32_TIM3_IS_USED) -#error "ST requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif - -#if defined(STM32_TIM3_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM3 -#define ST_LLD_NUM_ALARMS STM32_TIM3_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 TRUE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 4 - -#if defined(STM32_TIM4_IS_USED) -#error "ST requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif - -#if defined(STM32_TIM4_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM4 -#define ST_LLD_NUM_ALARMS STM32_TIM4_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 TRUE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 5 - -#if defined(STM32_TIM5_IS_USED) -#error "ST requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif - -#if defined(STM32_TIM5_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM5 -#define ST_LLD_NUM_ALARMS STM32_TIM5_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 TRUE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 9 - -#if defined(STM32_TIM9_IS_USED) -#error "ST requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif - -#if defined(STM32_TIM9_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM9 -#define ST_LLD_NUM_ALARMS STM32_TIM9_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 TRUE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 10 - -#if defined(STM32_TIM10_IS_USED) -#error "ST requires TIM10 but the timer is already used" -#else -#define STM32_TIM10_IS_USED -#endif - -#if defined(STM32_TIM10_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM10 -#define ST_LLD_NUM_ALARMS STM32_TIM10_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 TRUE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 11 - -#if defined(STM32_TIM11_IS_USED) -#error "ST requires TIM11 but the timer is already used" -#else -#define STM32_TIM11_IS_USED -#endif - -#if defined(STM32_TIM11_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM11 -#define ST_LLD_NUM_ALARMS STM32_TIM11_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 TRUE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 12 - -#if defined(STM32_TIM12_IS_USED) -#error "ST requires TIM12 but the timer is already used" -#else -#define STM32_TIM12_IS_USED -#endif - -#if defined(STM32_TIM12_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM12 -#define ST_LLD_NUM_ALARMS STM32_TIM12_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 TRUE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 13 - -#if defined(STM32_TIM13_IS_USED) -#error "ST requires TIM13 but the timer is already used" -#else -#define STM32_TIM13_IS_USED -#endif - -#if defined(STM32_TIM13_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM13 -#define ST_LLD_NUM_ALARMS STM32_TIM13_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 TRUE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 14 - -#if defined(STM32_TIM14_IS_USED) -#error "ST requires TIM14 but the timer is already used" -#else -#define STM32_TIM14_IS_USED -#endif - -#if defined(STM32_TIM14_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM14 -#define ST_LLD_NUM_ALARMS STM32_TIM14_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 TRUE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 21 - -#if defined(STM32_TIM21_IS_USED) -#error "ST requires TIM21 but the timer is already used" -#else -#define STM32_TIM21_IS_USED -#endif - -#if defined(STM32_TIM21_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM21 -#define ST_LLD_NUM_ALARMS STM32_TIM21_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 TRUE -#define STM32_ST_USE_TIM22 FALSE - -#elif STM32_ST_USE_TIMER == 22 - -#if defined(STM32_TIM22_IS_USED) -#error "ST requires TIM22 but the timer is already used" -#else -#define STM32_TIM22_IS_USED -#endif - -#if defined(STM32_TIM22_SUPPRESS_ISR) -#define STM32_SYSTICK_SUPPRESS_ISR -#endif - -#define STM32_ST_TIM STM32_TIM22 -#define ST_LLD_NUM_ALARMS STM32_TIM22_CHANNELS -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 TRUE - -#else -#error "STM32_ST_USE_TIMER specifies an unsupported timer" -#endif - -#if defined(STM32_ST_ENFORCE_ALARMS) - -#if (STM32_ST_ENFORCE_ALARMS < 1) || (STM32_ST_ENFORCE_ALARMS > ST_LLD_NUM_ALARMS) -#error "invalid STM32_ST_ENFORCE_ALARMS value" -#endif - -#undef ST_LLD_NUM_ALARMS -#define ST_LLD_NUM_ALARMS STM32_ST_ENFORCE_ALARMS -#endif - -#elif OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - -#define STM32_ST_USE_SYSTICK TRUE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#else - -#define STM32_ST_USE_SYSTICK FALSE -#define STM32_ST_USE_TIM2 FALSE -#define STM32_ST_USE_TIM3 FALSE -#define STM32_ST_USE_TIM4 FALSE -#define STM32_ST_USE_TIM5 FALSE -#define STM32_ST_USE_TIM9 FALSE -#define STM32_ST_USE_TIM10 FALSE -#define STM32_ST_USE_TIM11 FALSE -#define STM32_ST_USE_TIM12 FALSE -#define STM32_ST_USE_TIM13 FALSE -#define STM32_ST_USE_TIM14 FALSE -#define STM32_ST_USE_TIM21 FALSE -#define STM32_ST_USE_TIM22 FALSE - -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void st_lld_init(void); - void st_lld_serve_interrupt(void); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Driver inline functions. */ -/*===========================================================================*/ - - -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) - -/** - * @brief Returns the time counter value. - * - * @return The counter value. - * - * @notapi - */ -static inline systime_t st_lld_get_counter(void) { - - return (systime_t)STM32_ST_TIM->CNT; -} - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * - * @param[in] abstime the time to be set for the first alarm - * - * @notapi - */ -static inline void st_lld_start_alarm(systime_t abstime) { - - STM32_ST_TIM->CCR[0] = (uint32_t)abstime; - STM32_ST_TIM->SR = 0; -#if ST_LLD_NUM_ALARMS == 1 - STM32_ST_TIM->DIER = STM32_TIM_DIER_CC1IE; -#else - STM32_ST_TIM->DIER |= STM32_TIM_DIER_CC1IE; -#endif -} - -/** - * @brief Stops the alarm interrupt. - * - * @notapi - */ -static inline void st_lld_stop_alarm(void) { - -#if ST_LLD_NUM_ALARMS == 1 - STM32_ST_TIM->DIER = 0U; -#else - STM32_ST_TIM->DIER &= ~STM32_TIM_DIER_CC1IE; -#endif -} - -/** - * @brief Sets the alarm time. - * - * @param[in] abstime the time to be set for the next alarm - * - * @notapi - */ -static inline void st_lld_set_alarm(systime_t abstime) { - - STM32_ST_TIM->CCR[0] = (uint32_t)abstime; -} - -/** - * @brief Returns the current alarm time. - * - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t st_lld_get_alarm(void) { - - return (systime_t)STM32_ST_TIM->CCR[0]; -} - -/** - * @brief Determines if the alarm is active. - * - * @return The alarm status. - * @retval false if the alarm is not active. - * @retval true is the alarm is active - * - * @notapi - */ -static inline bool st_lld_is_alarm_active(void) { - - return (bool)((STM32_ST_TIM->DIER & STM32_TIM_DIER_CC1IE) != 0); -} - -#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__) -/** - * @brief Starts an alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @param[in] abstime the time to be set for the first alarm - * @param[in] alarm alarm channel number - * - * @notapi - */ -static inline void st_lld_start_alarm_n(unsigned alarm, systime_t abstime) { - - - STM32_ST_TIM->CCR[alarm] = (uint32_t)abstime; - STM32_ST_TIM->SR = 0; - STM32_ST_TIM->DIER |= (STM32_TIM_DIER_CC1IE << alarm); -} - -/** - * @brief Stops an alarm interrupt. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @param[in] alarm alarm channel number - * - * @notapi - */ -static inline void st_lld_stop_alarm_n(unsigned alarm) { - - STM32_ST_TIM->DIER &= ~(STM32_TIM_DIER_CC1IE << alarm); -} - -/** - * @brief Sets an alarm time. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @param[in] alarm alarm channel number - * @param[in] abstime the time to be set for the next alarm - * - * @notapi - */ -static inline void st_lld_set_alarm_n(unsigned alarm, systime_t abstime) { - - STM32_ST_TIM->CCR[alarm] = (uint32_t)abstime; -} - -/** - * @brief Returns an alarm current time. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @param[in] alarm alarm channel number - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t st_lld_get_alarm_n(unsigned alarm) { - - return (systime_t)STM32_ST_TIM->CCR[alarm]; -} - -/** - * @brief Determines if an alarm is active. - * - * @param[in] alarm alarm channel number - * @return The alarm status. - * @retval false if the alarm is not active. - * @retval true is the alarm is active - * - * @notapi - */ -static inline bool st_lld_is_alarm_active_n(unsigned alarm) { - - return (bool)((STM32_ST_TIM->DIER & (STM32_TIM_DIER_CC1IE << alarm)) != 0); -} -#endif /* ST_LLD_NUM_ALARMS > 1 */ - -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ - -#endif /* HAL_ST_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/hal_st_lld.h + * @brief ST Driver subsystem low level driver header. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup ST + * @{ + */ + +#ifndef HAL_ST_LLD_H +#define HAL_ST_LLD_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* Feature currently disabled.*/ +#define STM32_ST_ENFORCE_ALARMS 1 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SysTick timer IRQ priority. + */ +#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ST_IRQ_PRIORITY 8 +#endif + +/** + * @brief TIMx unit (by number) to be used for free running operations. + * @note You must select a 32 bits timer if a 32 bits @p systick_t type + * is required. + * @note Timers 2, 3, 4, 5, 21 and 22 are supported. + */ +#if !defined(STM32_ST_USE_TIMER) || defined(__DOXYGEN__) +#define STM32_ST_USE_TIMER 2 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* This has to go after transition to shared handlers is complete for all + platforms.*/ +#if !defined(STM32_HAS_TIM2) +#define STM32_HAS_TIM2 FALSE +#endif + +#if !defined(STM32_HAS_TIM3) +#define STM32_HAS_TIM3 FALSE +#endif + +#if !defined(STM32_HAS_TIM4) +#define STM32_HAS_TIM4 FALSE +#endif + +#if !defined(STM32_HAS_TIM5) +#define STM32_HAS_TIM5 FALSE +#endif + +#if !defined(STM32_HAS_TIM9) +#define STM32_HAS_TIM9 FALSE +#endif + +#if !defined(STM32_HAS_TIM10) +#define STM32_HAS_TIM10 FALSE +#endif + +#if !defined(STM32_HAS_TIM11) +#define STM32_HAS_TIM11 FALSE +#endif + +#if !defined(STM32_HAS_TIM12) +#define STM32_HAS_TIM12 FALSE +#endif + +#if !defined(STM32_HAS_TIM13) +#define STM32_HAS_TIM13 FALSE +#endif + +#if !defined(STM32_HAS_TIM14) +#define STM32_HAS_TIM14 FALSE +#endif + +#if !defined(STM32_HAS_TIM21) +#define STM32_HAS_TIM21 FALSE +#endif + +#if !defined(STM32_HAS_TIM22) +#define STM32_HAS_TIM22 FALSE +#endif +/**/ + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + +#if STM32_ST_USE_TIMER == 2 + +#if defined(STM32_TIM2_IS_USED) +#error "ST requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif + +#if defined(STM32_TIM2_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM2 +#define ST_LLD_NUM_ALARMS STM32_TIM2_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 TRUE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 3 + +#if defined(STM32_TIM3_IS_USED) +#error "ST requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif + +#if defined(STM32_TIM3_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM3 +#define ST_LLD_NUM_ALARMS STM32_TIM3_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 TRUE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 4 + +#if defined(STM32_TIM4_IS_USED) +#error "ST requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif + +#if defined(STM32_TIM4_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM4 +#define ST_LLD_NUM_ALARMS STM32_TIM4_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 TRUE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 5 + +#if defined(STM32_TIM5_IS_USED) +#error "ST requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif + +#if defined(STM32_TIM5_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM5 +#define ST_LLD_NUM_ALARMS STM32_TIM5_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 TRUE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 9 + +#if defined(STM32_TIM9_IS_USED) +#error "ST requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif + +#if defined(STM32_TIM9_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM9 +#define ST_LLD_NUM_ALARMS STM32_TIM9_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 TRUE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 10 + +#if defined(STM32_TIM10_IS_USED) +#error "ST requires TIM10 but the timer is already used" +#else +#define STM32_TIM10_IS_USED +#endif + +#if defined(STM32_TIM10_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM10 +#define ST_LLD_NUM_ALARMS STM32_TIM10_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 TRUE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 11 + +#if defined(STM32_TIM11_IS_USED) +#error "ST requires TIM11 but the timer is already used" +#else +#define STM32_TIM11_IS_USED +#endif + +#if defined(STM32_TIM11_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM11 +#define ST_LLD_NUM_ALARMS STM32_TIM11_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 TRUE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 12 + +#if defined(STM32_TIM12_IS_USED) +#error "ST requires TIM12 but the timer is already used" +#else +#define STM32_TIM12_IS_USED +#endif + +#if defined(STM32_TIM12_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM12 +#define ST_LLD_NUM_ALARMS STM32_TIM12_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 TRUE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 13 + +#if defined(STM32_TIM13_IS_USED) +#error "ST requires TIM13 but the timer is already used" +#else +#define STM32_TIM13_IS_USED +#endif + +#if defined(STM32_TIM13_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM13 +#define ST_LLD_NUM_ALARMS STM32_TIM13_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 TRUE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 14 + +#if defined(STM32_TIM14_IS_USED) +#error "ST requires TIM14 but the timer is already used" +#else +#define STM32_TIM14_IS_USED +#endif + +#if defined(STM32_TIM14_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM14 +#define ST_LLD_NUM_ALARMS STM32_TIM14_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 TRUE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 21 + +#if defined(STM32_TIM21_IS_USED) +#error "ST requires TIM21 but the timer is already used" +#else +#define STM32_TIM21_IS_USED +#endif + +#if defined(STM32_TIM21_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM21 +#define ST_LLD_NUM_ALARMS STM32_TIM21_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 TRUE +#define STM32_ST_USE_TIM22 FALSE + +#elif STM32_ST_USE_TIMER == 22 + +#if defined(STM32_TIM22_IS_USED) +#error "ST requires TIM22 but the timer is already used" +#else +#define STM32_TIM22_IS_USED +#endif + +#if defined(STM32_TIM22_SUPPRESS_ISR) +#define STM32_SYSTICK_SUPPRESS_ISR +#endif + +#define STM32_ST_TIM STM32_TIM22 +#define ST_LLD_NUM_ALARMS STM32_TIM22_CHANNELS +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 TRUE + +#else +#error "STM32_ST_USE_TIMER specifies an unsupported timer" +#endif + +#if defined(STM32_ST_ENFORCE_ALARMS) + +#if (STM32_ST_ENFORCE_ALARMS < 1) || (STM32_ST_ENFORCE_ALARMS > ST_LLD_NUM_ALARMS) +#error "invalid STM32_ST_ENFORCE_ALARMS value" +#endif + +#undef ST_LLD_NUM_ALARMS +#define ST_LLD_NUM_ALARMS STM32_ST_ENFORCE_ALARMS +#endif + +#elif OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + +#define STM32_ST_USE_SYSTICK TRUE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#else + +#define STM32_ST_USE_SYSTICK FALSE +#define STM32_ST_USE_TIM2 FALSE +#define STM32_ST_USE_TIM3 FALSE +#define STM32_ST_USE_TIM4 FALSE +#define STM32_ST_USE_TIM5 FALSE +#define STM32_ST_USE_TIM9 FALSE +#define STM32_ST_USE_TIM10 FALSE +#define STM32_ST_USE_TIM11 FALSE +#define STM32_ST_USE_TIM12 FALSE +#define STM32_ST_USE_TIM13 FALSE +#define STM32_ST_USE_TIM14 FALSE +#define STM32_ST_USE_TIM21 FALSE +#define STM32_ST_USE_TIM22 FALSE + +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void st_lld_init(void); + void st_lld_serve_interrupt(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) + +/** + * @brief Returns the time counter value. + * + * @return The counter value. + * + * @notapi + */ +static inline systime_t st_lld_get_counter(void) { + + return (systime_t)STM32_ST_TIM->CNT; +} + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] abstime the time to be set for the first alarm + * + * @notapi + */ +static inline void st_lld_start_alarm(systime_t abstime) { + + STM32_ST_TIM->CCR[0] = (uint32_t)abstime; + STM32_ST_TIM->SR = 0; +#if ST_LLD_NUM_ALARMS == 1 + STM32_ST_TIM->DIER = STM32_TIM_DIER_CC1IE; +#else + STM32_ST_TIM->DIER |= STM32_TIM_DIER_CC1IE; +#endif +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void st_lld_stop_alarm(void) { + +#if ST_LLD_NUM_ALARMS == 1 + STM32_ST_TIM->DIER = 0U; +#else + STM32_ST_TIM->DIER &= ~STM32_TIM_DIER_CC1IE; +#endif +} + +/** + * @brief Sets the alarm time. + * + * @param[in] abstime the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm(systime_t abstime) { + + STM32_ST_TIM->CCR[0] = (uint32_t)abstime; +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm(void) { + + return (systime_t)STM32_ST_TIM->CCR[0]; +} + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active(void) { + + return (bool)((STM32_ST_TIM->DIER & STM32_TIM_DIER_CC1IE) != 0); +} + +#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__) +/** + * @brief Starts an alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] abstime the time to be set for the first alarm + * @param[in] alarm alarm channel number + * + * @notapi + */ +static inline void st_lld_start_alarm_n(unsigned alarm, systime_t abstime) { + + + STM32_ST_TIM->CCR[alarm] = (uint32_t)abstime; + STM32_ST_TIM->SR = 0; + STM32_ST_TIM->DIER |= (STM32_TIM_DIER_CC1IE << alarm); +} + +/** + * @brief Stops an alarm interrupt. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] alarm alarm channel number + * + * @notapi + */ +static inline void st_lld_stop_alarm_n(unsigned alarm) { + + STM32_ST_TIM->DIER &= ~(STM32_TIM_DIER_CC1IE << alarm); +} + +/** + * @brief Sets an alarm time. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] alarm alarm channel number + * @param[in] abstime the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm_n(unsigned alarm, systime_t abstime) { + + STM32_ST_TIM->CCR[alarm] = (uint32_t)abstime; +} + +/** + * @brief Returns an alarm current time. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] alarm alarm channel number + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm_n(unsigned alarm) { + + return (systime_t)STM32_ST_TIM->CCR[alarm]; +} + +/** + * @brief Determines if an alarm is active. + * + * @param[in] alarm alarm channel number + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active_n(unsigned alarm) { + + return (bool)((STM32_ST_TIM->DIER & (STM32_TIM_DIER_CC1IE << alarm)) != 0); +} +#endif /* ST_LLD_NUM_ALARMS > 1 */ + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +#endif /* HAL_ST_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h b/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h index 81d8c094e3..d15e600d28 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h +++ b/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h @@ -1,566 +1,566 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file TIMv1/stm32_tim.h - * @brief STM32 TIM units common header. - * @note This file requires definitions from the ST STM32 header file. - * - * @addtogroup STM32_TIMv1 - * @{ - */ - -#ifndef STM32_TIM_H -#define STM32_TIM_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name TIM_CR1 register - * @{ - */ -#define STM32_TIM_CR1_CEN (1U << 0) -#define STM32_TIM_CR1_UDIS (1U << 1) -#define STM32_TIM_CR1_URS (1U << 2) -#define STM32_TIM_CR1_OPM (1U << 3) -#define STM32_TIM_CR1_DIR (1U << 4) - -#define STM32_TIM_CR1_CMS_MASK (3U << 5) -#define STM32_TIM_CR1_CMS(n) ((n) << 5) - -#define STM32_TIM_CR1_ARPE (1U << 7) - -#define STM32_TIM_CR1_CKD_MASK (3U << 8) -#define STM32_TIM_CR1_CKD(n) ((n) << 8) - -#define STM32_TIM_CR1_UIFREMAP (1U << 11) -/** @} */ - -/** - * @name TIM_CR2 register - * @{ - */ -#define STM32_TIM_CR2_CCPC (1U << 0) -#define STM32_TIM_CR2_CCUS (1U << 2) -#define STM32_TIM_CR2_CCDS (1U << 3) - -#define STM32_TIM_CR2_MMS_MASK (7U << 4) -#define STM32_TIM_CR2_MMS(n) ((n) << 4) - -#define STM32_TIM_CR2_TI1S (1U << 7) -#define STM32_TIM_CR2_OIS1 (1U << 8) -#define STM32_TIM_CR2_OIS1N (1U << 9) -#define STM32_TIM_CR2_OIS2 (1U << 10) -#define STM32_TIM_CR2_OIS2N (1U << 11) -#define STM32_TIM_CR2_OIS3 (1U << 12) -#define STM32_TIM_CR2_OIS3N (1U << 13) -#define STM32_TIM_CR2_OIS4 (1U << 14) -#define STM32_TIM_CR2_OIS5 (1U << 16) -#define STM32_TIM_CR2_OIS6 (1U << 18) - -#define STM32_TIM_CR2_MMS2_MASK (15U << 20) -#define STM32_TIM_CR2_MMS2(n) ((n) << 20) -/** @} */ - -/** - * @name TIM_SMCR register - * @{ - */ -#define STM32_TIM_SMCR_SMS_MASK ((7U << 0) | (1U << 16)) -#define STM32_TIM_SMCR_SMS(n) ((((n) & 7) << 0) | \ - (((n) >> 3) << 16)) - -#define STM32_TIM_SMCR_OCCS (1U << 3) - -#define STM32_TIM_SMCR_TS_MASK (7U << 4) -#define STM32_TIM_SMCR_TS(n) ((n) << 4) - -#define STM32_TIM_SMCR_MSM (1U << 7) - -#define STM32_TIM_SMCR_ETF_MASK (15U << 8) -#define STM32_TIM_SMCR_ETF(n) ((n) << 8) - -#define STM32_TIM_SMCR_ETPS_MASK (3U << 12) -#define STM32_TIM_SMCR_ETPS(n) ((n) << 12) - -#define STM32_TIM_SMCR_ECE (1U << 14) -#define STM32_TIM_SMCR_ETP (1U << 15) -/** @} */ - -/** - * @name TIM_DIER register - * @{ - */ -#define STM32_TIM_DIER_UIE (1U << 0) -#define STM32_TIM_DIER_CC1IE (1U << 1) -#define STM32_TIM_DIER_CC2IE (1U << 2) -#define STM32_TIM_DIER_CC3IE (1U << 3) -#define STM32_TIM_DIER_CC4IE (1U << 4) -#define STM32_TIM_DIER_COMIE (1U << 5) -#define STM32_TIM_DIER_TIE (1U << 6) -#define STM32_TIM_DIER_BIE (1U << 7) -#define STM32_TIM_DIER_UDE (1U << 8) -#define STM32_TIM_DIER_CC1DE (1U << 9) -#define STM32_TIM_DIER_CC2DE (1U << 10) -#define STM32_TIM_DIER_CC3DE (1U << 11) -#define STM32_TIM_DIER_CC4DE (1U << 12) -#define STM32_TIM_DIER_COMDE (1U << 13) -#define STM32_TIM_DIER_TDE (1U << 14) - -#define STM32_TIM_DIER_IRQ_MASK (STM32_TIM_DIER_UIE | \ - STM32_TIM_DIER_CC1IE | \ - STM32_TIM_DIER_CC2IE | \ - STM32_TIM_DIER_CC3IE | \ - STM32_TIM_DIER_CC4IE | \ - STM32_TIM_DIER_COMIE | \ - STM32_TIM_DIER_TIE | \ - STM32_TIM_DIER_BIE) - -/** @} */ - -/** - * @name TIM_SR register - * @{ - */ -#define STM32_TIM_SR_UIF (1U << 0) -#define STM32_TIM_SR_CC1IF (1U << 1) -#define STM32_TIM_SR_CC2IF (1U << 2) -#define STM32_TIM_SR_CC3IF (1U << 3) -#define STM32_TIM_SR_CC4IF (1U << 4) -#define STM32_TIM_SR_COMIF (1U << 5) -#define STM32_TIM_SR_TIF (1U << 6) -#define STM32_TIM_SR_BIF (1U << 7) -#define STM32_TIM_SR_B2IF (1U << 8) -#define STM32_TIM_SR_CC1OF (1U << 9) -#define STM32_TIM_SR_CC2OF (1U << 10) -#define STM32_TIM_SR_CC3OF (1U << 11) -#define STM32_TIM_SR_CC4OF (1U << 12) -#define STM32_TIM_SR_CC5IF (1U << 16) -#define STM32_TIM_SR_CC6IF (1U << 17) -/** @} */ - -/** - * @name TIM_EGR register - * @{ - */ -#define STM32_TIM_EGR_UG (1U << 0) -#define STM32_TIM_EGR_CC1G (1U << 1) -#define STM32_TIM_EGR_CC2G (1U << 2) -#define STM32_TIM_EGR_CC3G (1U << 3) -#define STM32_TIM_EGR_CC4G (1U << 4) -#define STM32_TIM_EGR_COMG (1U << 5) -#define STM32_TIM_EGR_TG (1U << 6) -#define STM32_TIM_EGR_BG (1U << 7) -#define STM32_TIM_EGR_B2G (1U << 8) -/** @} */ - -/** - * @name TIM_CCMR1 register (output) - * @{ - */ -#define STM32_TIM_CCMR1_CC1S_MASK (3U << 0) -#define STM32_TIM_CCMR1_CC1S(n) ((n) << 0) - -#define STM32_TIM_CCMR1_OC1FE (1U << 2) -#define STM32_TIM_CCMR1_OC1PE (1U << 3) - -#define STM32_TIM_CCMR1_OC1M_MASK ((7U << 4) | (1U << 16)) -#define STM32_TIM_CCMR1_OC1M(n) ((((n) & 7) << 4) | \ - (((n) >> 3) << 16)) - -#define STM32_TIM_CCMR1_OC1CE (1U << 7) - -#define STM32_TIM_CCMR1_CC2S_MASK (3U << 8) -#define STM32_TIM_CCMR1_CC2S(n) ((n) << 8) - -#define STM32_TIM_CCMR1_OC2FE (1U << 10) -#define STM32_TIM_CCMR1_OC2PE (1U << 11) - -#define STM32_TIM_CCMR1_OC2M_MASK ((7U << 12) | (1U << 24)) -#define STM32_TIM_CCMR1_OC2M(n) ((((n) & 7) << 12) | \ - (((n) >> 3) << 24)) - -#define STM32_TIM_CCMR1_OC2CE (1U << 15) -/** @} */ - -/** - * @name CCMR1 register (input) - * @{ - */ -#define STM32_TIM_CCMR1_IC1PSC_MASK (3U << 2) -#define STM32_TIM_CCMR1_IC1PSC(n) ((n) << 2) - -#define STM32_TIM_CCMR1_IC1F_MASK (15U << 4) -#define STM32_TIM_CCMR1_IC1F(n) ((n) << 4) - -#define STM32_TIM_CCMR1_IC2PSC_MASK (3U << 10) -#define STM32_TIM_CCMR1_IC2PSC(n) ((n) << 10) - -#define STM32_TIM_CCMR1_IC2F_MASK (15U << 12) -#define STM32_TIM_CCMR1_IC2F(n) ((n) << 12) -/** @} */ - -/** - * @name TIM_CCMR2 register (output) - * @{ - */ -#define STM32_TIM_CCMR2_CC3S_MASK (3U << 0) -#define STM32_TIM_CCMR2_CC3S(n) ((n) << 0) - -#define STM32_TIM_CCMR2_OC3FE (1U << 2) -#define STM32_TIM_CCMR2_OC3PE (1U << 3) - -#define STM32_TIM_CCMR2_OC3M_MASK ((7U << 4) | (1U << 16)) -#define STM32_TIM_CCMR2_OC3M(n) ((((n) & 7) << 4) | \ - (((n) >> 3) << 16)) - -#define STM32_TIM_CCMR2_OC3CE (1U << 7) - -#define STM32_TIM_CCMR2_CC4S_MASK (3U << 8) -#define STM32_TIM_CCMR2_CC4S(n) ((n) << 8) - -#define STM32_TIM_CCMR2_OC4FE (1U << 10) -#define STM32_TIM_CCMR2_OC4PE (1U << 11) - -#define STM32_TIM_CCMR2_OC4M_MASK ((7U << 12) | (1U << 24)) -#define STM32_TIM_CCMR2_OC4M(n) ((((n) & 7) << 12) | \ - (((n) >> 3) << 24)) - -#define STM32_TIM_CCMR2_OC4CE (1U << 15) -/** @} */ - -/** - * @name TIM_CCMR2 register (input) - * @{ - */ -#define STM32_TIM_CCMR2_IC3PSC_MASK (3U << 2) -#define STM32_TIM_CCMR2_IC3PSC(n) ((n) << 2) - -#define STM32_TIM_CCMR2_IC3F_MASK (15U << 4) -#define STM32_TIM_CCMR2_IC3F(n) ((n) << 4) - -#define STM32_TIM_CCMR2_IC4PSC_MASK (3U << 10) -#define STM32_TIM_CCMR2_IC4PSC(n) ((n) << 10) - -#define STM32_TIM_CCMR2_IC4F_MASK (15U << 12) -#define STM32_TIM_CCMR2_IC4F(n) ((n) << 12) -/** @} */ - -/** - * @name TIM_CCER register - * @{ - */ -#define STM32_TIM_CCER_CC1E (1U << 0) -#define STM32_TIM_CCER_CC1P (1U << 1) -#define STM32_TIM_CCER_CC1NE (1U << 2) -#define STM32_TIM_CCER_CC1NP (1U << 3) -#define STM32_TIM_CCER_CC2E (1U << 4) -#define STM32_TIM_CCER_CC2P (1U << 5) -#define STM32_TIM_CCER_CC2NE (1U << 6) -#define STM32_TIM_CCER_CC2NP (1U << 7) -#define STM32_TIM_CCER_CC3E (1U << 8) -#define STM32_TIM_CCER_CC3P (1U << 9) -#define STM32_TIM_CCER_CC3NE (1U << 10) -#define STM32_TIM_CCER_CC3NP (1U << 11) -#define STM32_TIM_CCER_CC4E (1U << 12) -#define STM32_TIM_CCER_CC4P (1U << 13) -#define STM32_TIM_CCER_CC4NE (1U << 14) -#define STM32_TIM_CCER_CC4NP (1U << 15) -#define STM32_TIM_CCER_CC5E (1U << 16) -#define STM32_TIM_CCER_CC5P (1U << 17) -#define STM32_TIM_CCER_CC6E (1U << 20) -#define STM32_TIM_CCER_CC6P (1U << 21) -/** @} */ - -/** - * @name TIM_CNT register - * @{ - */ -#define STM32_TIM_CNT_UIFCPY (1U << 31) -/** @} */ - -/** - * @name TIM_BDTR register - * @{ - */ -#define STM32_TIM_BDTR_DTG_MASK (255U << 0) -#define STM32_TIM_BDTR_DTG(n) ((n) << 0) - -#define STM32_TIM_BDTR_LOCK_MASK (3U << 8) -#define STM32_TIM_BDTR_LOCK(n) ((n) << 8) - -#define STM32_TIM_BDTR_OSSI (1U << 10) -#define STM32_TIM_BDTR_OSSR (1U << 11) -#define STM32_TIM_BDTR_BKE (1U << 12) -#define STM32_TIM_BDTR_BKP (1U << 13) -#define STM32_TIM_BDTR_AOE (1U << 14) -#define STM32_TIM_BDTR_MOE (1U << 15) - -#define STM32_TIM_BDTR_BKF_MASK (15U << 16) -#define STM32_TIM_BDTR_BKF(n) ((n) << 16) -#define STM32_TIM_BDTR_BK2F_MASK (15U << 20) -#define STM32_TIM_BDTR_BK2F(n) ((n) << 20) - -#define STM32_TIM_BDTR_BK2E (1U << 24) -#define STM32_TIM_BDTR_BK2P (1U << 25) -/** @} */ - -/** - * @name TIM_DCR register - * @{ - */ -#define STM32_TIM_DCR_DBA_MASK (31U << 0) -#define STM32_TIM_DCR_DBA(n) ((n) << 0) - -#define STM32_TIM_DCR_DBL_MASK (31U << 8) -#define STM32_TIM_DCR_DBL(n) ((n) << 8) -/** @} */ - -/** - * @name TIM16_OR register - * @{ - */ -#define STM32_TIM16_OR_TI1_RMP_MASK (3U << 6) -#define STM32_TIM16_OR_TI1_RMP(n) ((n) << 6) -/** @} */ - -/** - * @name TIM_OR register - * @{ - */ -#define STM32_TIM_OR_ETR_RMP_MASK (15U << 0) -#define STM32_TIM_OR_ETR_RMP(n) ((n) << 0) -/** @} */ - -/** - * @name TIM_CCMR3 register - * @{ - */ -#define STM32_TIM_CCMR3_OC5FE (1U << 2) -#define STM32_TIM_CCMR3_OC5PE (1U << 3) - -#define STM32_TIM_CCMR3_OC5M_MASK ((7U << 4) | (1U << 16)) -#define STM32_TIM_CCMR3_OC5M(n) ((((n) & 7) << 4) | \ - (((n) >> 2) << 16)) - -#define STM32_TIM_CCMR3_OC5CE (1U << 7) - -#define STM32_TIM_CCMR3_OC6FE (1U << 10) -#define STM32_TIM_CCMR3_OC6PE (1U << 11) - -#define STM32_TIM_CCMR3_OC6M_MASK ((7U << 12) | (1U << 24)) -#define STM32_TIM_CCMR3_OC6M(n) ((((n) & 7) << 12) | \ - (((n) >> 2) << 24)) - -#define STM32_TIM_CCMR3_OC6CE (1U << 15) -/** @} */ - -/** - * @name LPTIM_ISR register - * @{ - */ -#define STM32_LPTIM_ISR_CMPM (1U << 0) -#define STM32_LPTIM_ISR_ARRM (1U << 1) -#define STM32_LPTIM_ISR_EXTTRIG (1U << 2) -#define STM32_LPTIM_ISR_CMPOK (1U << 3) -#define STM32_LPTIM_ISR_ARROK (1U << 4) -#define STM32_LPTIM_ISR_UP (1U << 5) -#define STM32_LPTIM_ISR_DOWN (1U << 6) -/** @} */ - -/** - * @name LPTIM_ICR register - * @{ - */ -#define STM32_LPTIM_ICR_CMPMCF (1U << 0) -#define STM32_LPTIM_ICR_ARRMCF (1U << 1) -#define STM32_LPTIM_ICR_EXTTRIGCF (1U << 2) -#define STM32_LPTIM_ICR_CMPOKCF (1U << 3) -#define STM32_LPTIM_ICR_ARROKCF (1U << 4) -#define STM32_LPTIM_ICR_UPCF (1U << 5) -#define STM32_LPTIM_ICR_DOWNCF (1U << 6) -/** @} */ - -/** - * @name LPTIM_IER register - * @{ - */ -#define STM32_LPTIM_IER_CMPMIE (1U << 0) -#define STM32_LPTIM_IER_ARRMIE (1U << 1) -#define STM32_LPTIM_IER_EXTTRIGIE (1U << 2) -#define STM32_LPTIM_IER_CMPOKIE (1U << 3) -#define STM32_LPTIM_IER_ARROKIE (1U << 4) -#define STM32_LPTIM_IER_UPIE (1U << 5) -#define STM32_LPTIM_IER_DOWNIE (1U << 6) -/** @} */ - -/** - * @name LPTIM_CFGR register - * @{ - */ -#define STM32_LPTIM_CFGR_CKSEL (1U << 0) -#define STM32_LPTIM_CFGR_CKPOL_MASK (3U << 1) -#define STM32_LPTIM_CFGR_CKPOL(n) ((n) << 1) -#define STM32_LPTIM_CFGR_CKFLT_MASK (3U << 3) -#define STM32_LPTIM_CFGR_CKFLT(n) ((n) << 3) -#define STM32_LPTIM_CFGR_TRGFLT_MASK (3U << 6) -#define STM32_LPTIM_CFGR_TRGFLT(n) ((n) << 6) -#define STM32_LPTIM_CFGR_PRESC_MASK (7U << 9) -#define STM32_LPTIM_CFGR_PRESC(n) ((n) << 9) -#define STM32_LPTIM_CFGR_TRIGSEL_MASK (7U << 13) -#define STM32_LPTIM_CFGR_TRIGSEL(n) ((n) << 13) -#define STM32_LPTIM_CFGR_TRIGEN_MASK (3U << 17) -#define STM32_LPTIM_CFGR_TRIGEN(n) ((n) << 17) -#define STM32_LPTIM_CFGR_TIMOUT (1U << 19) -#define STM32_LPTIM_CFGR_WAVE (1U << 20) -#define STM32_LPTIM_CFGR_WAVPOL (1U << 21) -#define STM32_LPTIM_CFGR_PRELOAD (1U << 22) -#define STM32_LPTIM_CFGR_COUNTMODE (1U << 23) -#define STM32_LPTIM_CFGR_ENC (1U << 24) -/** @} */ - -/** - * @name LPTIM_CR register - * @{ - */ -#define STM32_LPTIM_CR_ENABLE (1U << 0) -#define STM32_LPTIM_CR_SNGSTRT (1U << 1) -#define STM32_LPTIM_CR_CNTSTRT (1U << 2) -/** @} */ - -/** - * @name LPTIM_OR register - * @{ - */ -#define STM32_LPTIM_OR_0 (1U << 0) -#define STM32_LPTIM_OR_1 (1U << 1) -/** @} */ - -/** - * @name TIM units references - * @{ - */ -#define STM32_TIM1 ((stm32_tim_t *)TIM1_BASE) -#define STM32_TIM2 ((stm32_tim_t *)TIM2_BASE) -#define STM32_TIM3 ((stm32_tim_t *)TIM3_BASE) -#define STM32_TIM4 ((stm32_tim_t *)TIM4_BASE) -#define STM32_TIM5 ((stm32_tim_t *)TIM5_BASE) -#define STM32_TIM6 ((stm32_tim_t *)TIM6_BASE) -#define STM32_TIM7 ((stm32_tim_t *)TIM7_BASE) -#define STM32_TIM8 ((stm32_tim_t *)TIM8_BASE) -#define STM32_TIM9 ((stm32_tim_t *)TIM9_BASE) -#define STM32_TIM10 ((stm32_tim_t *)TIM10_BASE) -#define STM32_TIM11 ((stm32_tim_t *)TIM11_BASE) -#define STM32_TIM12 ((stm32_tim_t *)TIM12_BASE) -#define STM32_TIM13 ((stm32_tim_t *)TIM13_BASE) -#define STM32_TIM14 ((stm32_tim_t *)TIM14_BASE) -#define STM32_TIM15 ((stm32_tim_t *)TIM15_BASE) -#define STM32_TIM16 ((stm32_tim_t *)TIM16_BASE) -#define STM32_TIM17 ((stm32_tim_t *)TIM17_BASE) -#define STM32_TIM18 ((stm32_tim_t *)TIM18_BASE) -#define STM32_TIM19 ((stm32_tim_t *)TIM19_BASE) -#define STM32_TIM20 ((stm32_tim_t *)TIM20_BASE) -#define STM32_TIM21 ((stm32_tim_t *)TIM21_BASE) -#define STM32_TIM22 ((stm32_tim_t *)TIM22_BASE) - -#define STM32_LPTIM1 ((stm32_lptim_t *)LPTIM1_BASE) -#define STM32_LPTIM2 ((stm32_lptim_t *)LPTIM2_BASE) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 TIM registers block. - * @note This is the most general known form, not all timers have - * necessarily all registers and bits. - */ -typedef struct { - volatile uint32_t CR1; - volatile uint32_t CR2; - volatile uint32_t SMCR; - volatile uint32_t DIER; - volatile uint32_t SR; - volatile uint32_t EGR; - volatile uint32_t CCMR1; - volatile uint32_t CCMR2; - volatile uint32_t CCER; - volatile uint32_t CNT; - volatile uint32_t PSC; - volatile uint32_t ARR; - volatile uint32_t RCR; - volatile uint32_t CCR[4]; - volatile uint32_t BDTR; -#if defined(STM32G4) - volatile uint32_t CCXR[2]; - volatile uint32_t CCMR3; - volatile uint32_t DTR2; - volatile uint32_t ECR; - volatile uint32_t TISEL; - volatile uint32_t AF1; - volatile uint32_t AF2; - volatile uint32_t OR; - volatile uint32_t RESERVED0[220]; - volatile uint32_t DCR; - volatile uint32_t DMAR; -#else - volatile uint32_t DCR; - volatile uint32_t DMAR; - volatile uint32_t OR; - volatile uint32_t CCMR3; - volatile uint32_t CCXR[2]; -#endif -} stm32_tim_t; - -/** - * @brief STM32 LPTIM registers block. - * @note This is the most general known form, not all timers have - * necessarily all registers and bits. - */ -typedef struct { - volatile uint32_t ISR; - volatile uint32_t ICR; - volatile uint32_t IER; - volatile uint32_t CFGR; - volatile uint32_t CR; - volatile uint32_t CMP; - volatile uint32_t ARR; - volatile uint32_t CNT; - volatile uint32_t OR; -} stm32_lptim_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* STM32_TIM_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file TIMv1/stm32_tim.h + * @brief STM32 TIM units common header. + * @note This file requires definitions from the ST STM32 header file. + * + * @addtogroup STM32_TIMv1 + * @{ + */ + +#ifndef STM32_TIM_H +#define STM32_TIM_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name TIM_CR1 register + * @{ + */ +#define STM32_TIM_CR1_CEN (1U << 0) +#define STM32_TIM_CR1_UDIS (1U << 1) +#define STM32_TIM_CR1_URS (1U << 2) +#define STM32_TIM_CR1_OPM (1U << 3) +#define STM32_TIM_CR1_DIR (1U << 4) + +#define STM32_TIM_CR1_CMS_MASK (3U << 5) +#define STM32_TIM_CR1_CMS(n) ((n) << 5) + +#define STM32_TIM_CR1_ARPE (1U << 7) + +#define STM32_TIM_CR1_CKD_MASK (3U << 8) +#define STM32_TIM_CR1_CKD(n) ((n) << 8) + +#define STM32_TIM_CR1_UIFREMAP (1U << 11) +/** @} */ + +/** + * @name TIM_CR2 register + * @{ + */ +#define STM32_TIM_CR2_CCPC (1U << 0) +#define STM32_TIM_CR2_CCUS (1U << 2) +#define STM32_TIM_CR2_CCDS (1U << 3) + +#define STM32_TIM_CR2_MMS_MASK (7U << 4) +#define STM32_TIM_CR2_MMS(n) ((n) << 4) + +#define STM32_TIM_CR2_TI1S (1U << 7) +#define STM32_TIM_CR2_OIS1 (1U << 8) +#define STM32_TIM_CR2_OIS1N (1U << 9) +#define STM32_TIM_CR2_OIS2 (1U << 10) +#define STM32_TIM_CR2_OIS2N (1U << 11) +#define STM32_TIM_CR2_OIS3 (1U << 12) +#define STM32_TIM_CR2_OIS3N (1U << 13) +#define STM32_TIM_CR2_OIS4 (1U << 14) +#define STM32_TIM_CR2_OIS5 (1U << 16) +#define STM32_TIM_CR2_OIS6 (1U << 18) + +#define STM32_TIM_CR2_MMS2_MASK (15U << 20) +#define STM32_TIM_CR2_MMS2(n) ((n) << 20) +/** @} */ + +/** + * @name TIM_SMCR register + * @{ + */ +#define STM32_TIM_SMCR_SMS_MASK ((7U << 0) | (1U << 16)) +#define STM32_TIM_SMCR_SMS(n) ((((n) & 7) << 0) | \ + (((n) >> 3) << 16)) + +#define STM32_TIM_SMCR_OCCS (1U << 3) + +#define STM32_TIM_SMCR_TS_MASK (7U << 4) +#define STM32_TIM_SMCR_TS(n) ((n) << 4) + +#define STM32_TIM_SMCR_MSM (1U << 7) + +#define STM32_TIM_SMCR_ETF_MASK (15U << 8) +#define STM32_TIM_SMCR_ETF(n) ((n) << 8) + +#define STM32_TIM_SMCR_ETPS_MASK (3U << 12) +#define STM32_TIM_SMCR_ETPS(n) ((n) << 12) + +#define STM32_TIM_SMCR_ECE (1U << 14) +#define STM32_TIM_SMCR_ETP (1U << 15) +/** @} */ + +/** + * @name TIM_DIER register + * @{ + */ +#define STM32_TIM_DIER_UIE (1U << 0) +#define STM32_TIM_DIER_CC1IE (1U << 1) +#define STM32_TIM_DIER_CC2IE (1U << 2) +#define STM32_TIM_DIER_CC3IE (1U << 3) +#define STM32_TIM_DIER_CC4IE (1U << 4) +#define STM32_TIM_DIER_COMIE (1U << 5) +#define STM32_TIM_DIER_TIE (1U << 6) +#define STM32_TIM_DIER_BIE (1U << 7) +#define STM32_TIM_DIER_UDE (1U << 8) +#define STM32_TIM_DIER_CC1DE (1U << 9) +#define STM32_TIM_DIER_CC2DE (1U << 10) +#define STM32_TIM_DIER_CC3DE (1U << 11) +#define STM32_TIM_DIER_CC4DE (1U << 12) +#define STM32_TIM_DIER_COMDE (1U << 13) +#define STM32_TIM_DIER_TDE (1U << 14) + +#define STM32_TIM_DIER_IRQ_MASK (STM32_TIM_DIER_UIE | \ + STM32_TIM_DIER_CC1IE | \ + STM32_TIM_DIER_CC2IE | \ + STM32_TIM_DIER_CC3IE | \ + STM32_TIM_DIER_CC4IE | \ + STM32_TIM_DIER_COMIE | \ + STM32_TIM_DIER_TIE | \ + STM32_TIM_DIER_BIE) + +/** @} */ + +/** + * @name TIM_SR register + * @{ + */ +#define STM32_TIM_SR_UIF (1U << 0) +#define STM32_TIM_SR_CC1IF (1U << 1) +#define STM32_TIM_SR_CC2IF (1U << 2) +#define STM32_TIM_SR_CC3IF (1U << 3) +#define STM32_TIM_SR_CC4IF (1U << 4) +#define STM32_TIM_SR_COMIF (1U << 5) +#define STM32_TIM_SR_TIF (1U << 6) +#define STM32_TIM_SR_BIF (1U << 7) +#define STM32_TIM_SR_B2IF (1U << 8) +#define STM32_TIM_SR_CC1OF (1U << 9) +#define STM32_TIM_SR_CC2OF (1U << 10) +#define STM32_TIM_SR_CC3OF (1U << 11) +#define STM32_TIM_SR_CC4OF (1U << 12) +#define STM32_TIM_SR_CC5IF (1U << 16) +#define STM32_TIM_SR_CC6IF (1U << 17) +/** @} */ + +/** + * @name TIM_EGR register + * @{ + */ +#define STM32_TIM_EGR_UG (1U << 0) +#define STM32_TIM_EGR_CC1G (1U << 1) +#define STM32_TIM_EGR_CC2G (1U << 2) +#define STM32_TIM_EGR_CC3G (1U << 3) +#define STM32_TIM_EGR_CC4G (1U << 4) +#define STM32_TIM_EGR_COMG (1U << 5) +#define STM32_TIM_EGR_TG (1U << 6) +#define STM32_TIM_EGR_BG (1U << 7) +#define STM32_TIM_EGR_B2G (1U << 8) +/** @} */ + +/** + * @name TIM_CCMR1 register (output) + * @{ + */ +#define STM32_TIM_CCMR1_CC1S_MASK (3U << 0) +#define STM32_TIM_CCMR1_CC1S(n) ((n) << 0) + +#define STM32_TIM_CCMR1_OC1FE (1U << 2) +#define STM32_TIM_CCMR1_OC1PE (1U << 3) + +#define STM32_TIM_CCMR1_OC1M_MASK ((7U << 4) | (1U << 16)) +#define STM32_TIM_CCMR1_OC1M(n) ((((n) & 7) << 4) | \ + (((n) >> 3) << 16)) + +#define STM32_TIM_CCMR1_OC1CE (1U << 7) + +#define STM32_TIM_CCMR1_CC2S_MASK (3U << 8) +#define STM32_TIM_CCMR1_CC2S(n) ((n) << 8) + +#define STM32_TIM_CCMR1_OC2FE (1U << 10) +#define STM32_TIM_CCMR1_OC2PE (1U << 11) + +#define STM32_TIM_CCMR1_OC2M_MASK ((7U << 12) | (1U << 24)) +#define STM32_TIM_CCMR1_OC2M(n) ((((n) & 7) << 12) | \ + (((n) >> 3) << 24)) + +#define STM32_TIM_CCMR1_OC2CE (1U << 15) +/** @} */ + +/** + * @name CCMR1 register (input) + * @{ + */ +#define STM32_TIM_CCMR1_IC1PSC_MASK (3U << 2) +#define STM32_TIM_CCMR1_IC1PSC(n) ((n) << 2) + +#define STM32_TIM_CCMR1_IC1F_MASK (15U << 4) +#define STM32_TIM_CCMR1_IC1F(n) ((n) << 4) + +#define STM32_TIM_CCMR1_IC2PSC_MASK (3U << 10) +#define STM32_TIM_CCMR1_IC2PSC(n) ((n) << 10) + +#define STM32_TIM_CCMR1_IC2F_MASK (15U << 12) +#define STM32_TIM_CCMR1_IC2F(n) ((n) << 12) +/** @} */ + +/** + * @name TIM_CCMR2 register (output) + * @{ + */ +#define STM32_TIM_CCMR2_CC3S_MASK (3U << 0) +#define STM32_TIM_CCMR2_CC3S(n) ((n) << 0) + +#define STM32_TIM_CCMR2_OC3FE (1U << 2) +#define STM32_TIM_CCMR2_OC3PE (1U << 3) + +#define STM32_TIM_CCMR2_OC3M_MASK ((7U << 4) | (1U << 16)) +#define STM32_TIM_CCMR2_OC3M(n) ((((n) & 7) << 4) | \ + (((n) >> 3) << 16)) + +#define STM32_TIM_CCMR2_OC3CE (1U << 7) + +#define STM32_TIM_CCMR2_CC4S_MASK (3U << 8) +#define STM32_TIM_CCMR2_CC4S(n) ((n) << 8) + +#define STM32_TIM_CCMR2_OC4FE (1U << 10) +#define STM32_TIM_CCMR2_OC4PE (1U << 11) + +#define STM32_TIM_CCMR2_OC4M_MASK ((7U << 12) | (1U << 24)) +#define STM32_TIM_CCMR2_OC4M(n) ((((n) & 7) << 12) | \ + (((n) >> 3) << 24)) + +#define STM32_TIM_CCMR2_OC4CE (1U << 15) +/** @} */ + +/** + * @name TIM_CCMR2 register (input) + * @{ + */ +#define STM32_TIM_CCMR2_IC3PSC_MASK (3U << 2) +#define STM32_TIM_CCMR2_IC3PSC(n) ((n) << 2) + +#define STM32_TIM_CCMR2_IC3F_MASK (15U << 4) +#define STM32_TIM_CCMR2_IC3F(n) ((n) << 4) + +#define STM32_TIM_CCMR2_IC4PSC_MASK (3U << 10) +#define STM32_TIM_CCMR2_IC4PSC(n) ((n) << 10) + +#define STM32_TIM_CCMR2_IC4F_MASK (15U << 12) +#define STM32_TIM_CCMR2_IC4F(n) ((n) << 12) +/** @} */ + +/** + * @name TIM_CCER register + * @{ + */ +#define STM32_TIM_CCER_CC1E (1U << 0) +#define STM32_TIM_CCER_CC1P (1U << 1) +#define STM32_TIM_CCER_CC1NE (1U << 2) +#define STM32_TIM_CCER_CC1NP (1U << 3) +#define STM32_TIM_CCER_CC2E (1U << 4) +#define STM32_TIM_CCER_CC2P (1U << 5) +#define STM32_TIM_CCER_CC2NE (1U << 6) +#define STM32_TIM_CCER_CC2NP (1U << 7) +#define STM32_TIM_CCER_CC3E (1U << 8) +#define STM32_TIM_CCER_CC3P (1U << 9) +#define STM32_TIM_CCER_CC3NE (1U << 10) +#define STM32_TIM_CCER_CC3NP (1U << 11) +#define STM32_TIM_CCER_CC4E (1U << 12) +#define STM32_TIM_CCER_CC4P (1U << 13) +#define STM32_TIM_CCER_CC4NE (1U << 14) +#define STM32_TIM_CCER_CC4NP (1U << 15) +#define STM32_TIM_CCER_CC5E (1U << 16) +#define STM32_TIM_CCER_CC5P (1U << 17) +#define STM32_TIM_CCER_CC6E (1U << 20) +#define STM32_TIM_CCER_CC6P (1U << 21) +/** @} */ + +/** + * @name TIM_CNT register + * @{ + */ +#define STM32_TIM_CNT_UIFCPY (1U << 31) +/** @} */ + +/** + * @name TIM_BDTR register + * @{ + */ +#define STM32_TIM_BDTR_DTG_MASK (255U << 0) +#define STM32_TIM_BDTR_DTG(n) ((n) << 0) + +#define STM32_TIM_BDTR_LOCK_MASK (3U << 8) +#define STM32_TIM_BDTR_LOCK(n) ((n) << 8) + +#define STM32_TIM_BDTR_OSSI (1U << 10) +#define STM32_TIM_BDTR_OSSR (1U << 11) +#define STM32_TIM_BDTR_BKE (1U << 12) +#define STM32_TIM_BDTR_BKP (1U << 13) +#define STM32_TIM_BDTR_AOE (1U << 14) +#define STM32_TIM_BDTR_MOE (1U << 15) + +#define STM32_TIM_BDTR_BKF_MASK (15U << 16) +#define STM32_TIM_BDTR_BKF(n) ((n) << 16) +#define STM32_TIM_BDTR_BK2F_MASK (15U << 20) +#define STM32_TIM_BDTR_BK2F(n) ((n) << 20) + +#define STM32_TIM_BDTR_BK2E (1U << 24) +#define STM32_TIM_BDTR_BK2P (1U << 25) +/** @} */ + +/** + * @name TIM_DCR register + * @{ + */ +#define STM32_TIM_DCR_DBA_MASK (31U << 0) +#define STM32_TIM_DCR_DBA(n) ((n) << 0) + +#define STM32_TIM_DCR_DBL_MASK (31U << 8) +#define STM32_TIM_DCR_DBL(n) ((n) << 8) +/** @} */ + +/** + * @name TIM16_OR register + * @{ + */ +#define STM32_TIM16_OR_TI1_RMP_MASK (3U << 6) +#define STM32_TIM16_OR_TI1_RMP(n) ((n) << 6) +/** @} */ + +/** + * @name TIM_OR register + * @{ + */ +#define STM32_TIM_OR_ETR_RMP_MASK (15U << 0) +#define STM32_TIM_OR_ETR_RMP(n) ((n) << 0) +/** @} */ + +/** + * @name TIM_CCMR3 register + * @{ + */ +#define STM32_TIM_CCMR3_OC5FE (1U << 2) +#define STM32_TIM_CCMR3_OC5PE (1U << 3) + +#define STM32_TIM_CCMR3_OC5M_MASK ((7U << 4) | (1U << 16)) +#define STM32_TIM_CCMR3_OC5M(n) ((((n) & 7) << 4) | \ + (((n) >> 2) << 16)) + +#define STM32_TIM_CCMR3_OC5CE (1U << 7) + +#define STM32_TIM_CCMR3_OC6FE (1U << 10) +#define STM32_TIM_CCMR3_OC6PE (1U << 11) + +#define STM32_TIM_CCMR3_OC6M_MASK ((7U << 12) | (1U << 24)) +#define STM32_TIM_CCMR3_OC6M(n) ((((n) & 7) << 12) | \ + (((n) >> 2) << 24)) + +#define STM32_TIM_CCMR3_OC6CE (1U << 15) +/** @} */ + +/** + * @name LPTIM_ISR register + * @{ + */ +#define STM32_LPTIM_ISR_CMPM (1U << 0) +#define STM32_LPTIM_ISR_ARRM (1U << 1) +#define STM32_LPTIM_ISR_EXTTRIG (1U << 2) +#define STM32_LPTIM_ISR_CMPOK (1U << 3) +#define STM32_LPTIM_ISR_ARROK (1U << 4) +#define STM32_LPTIM_ISR_UP (1U << 5) +#define STM32_LPTIM_ISR_DOWN (1U << 6) +/** @} */ + +/** + * @name LPTIM_ICR register + * @{ + */ +#define STM32_LPTIM_ICR_CMPMCF (1U << 0) +#define STM32_LPTIM_ICR_ARRMCF (1U << 1) +#define STM32_LPTIM_ICR_EXTTRIGCF (1U << 2) +#define STM32_LPTIM_ICR_CMPOKCF (1U << 3) +#define STM32_LPTIM_ICR_ARROKCF (1U << 4) +#define STM32_LPTIM_ICR_UPCF (1U << 5) +#define STM32_LPTIM_ICR_DOWNCF (1U << 6) +/** @} */ + +/** + * @name LPTIM_IER register + * @{ + */ +#define STM32_LPTIM_IER_CMPMIE (1U << 0) +#define STM32_LPTIM_IER_ARRMIE (1U << 1) +#define STM32_LPTIM_IER_EXTTRIGIE (1U << 2) +#define STM32_LPTIM_IER_CMPOKIE (1U << 3) +#define STM32_LPTIM_IER_ARROKIE (1U << 4) +#define STM32_LPTIM_IER_UPIE (1U << 5) +#define STM32_LPTIM_IER_DOWNIE (1U << 6) +/** @} */ + +/** + * @name LPTIM_CFGR register + * @{ + */ +#define STM32_LPTIM_CFGR_CKSEL (1U << 0) +#define STM32_LPTIM_CFGR_CKPOL_MASK (3U << 1) +#define STM32_LPTIM_CFGR_CKPOL(n) ((n) << 1) +#define STM32_LPTIM_CFGR_CKFLT_MASK (3U << 3) +#define STM32_LPTIM_CFGR_CKFLT(n) ((n) << 3) +#define STM32_LPTIM_CFGR_TRGFLT_MASK (3U << 6) +#define STM32_LPTIM_CFGR_TRGFLT(n) ((n) << 6) +#define STM32_LPTIM_CFGR_PRESC_MASK (7U << 9) +#define STM32_LPTIM_CFGR_PRESC(n) ((n) << 9) +#define STM32_LPTIM_CFGR_TRIGSEL_MASK (7U << 13) +#define STM32_LPTIM_CFGR_TRIGSEL(n) ((n) << 13) +#define STM32_LPTIM_CFGR_TRIGEN_MASK (3U << 17) +#define STM32_LPTIM_CFGR_TRIGEN(n) ((n) << 17) +#define STM32_LPTIM_CFGR_TIMOUT (1U << 19) +#define STM32_LPTIM_CFGR_WAVE (1U << 20) +#define STM32_LPTIM_CFGR_WAVPOL (1U << 21) +#define STM32_LPTIM_CFGR_PRELOAD (1U << 22) +#define STM32_LPTIM_CFGR_COUNTMODE (1U << 23) +#define STM32_LPTIM_CFGR_ENC (1U << 24) +/** @} */ + +/** + * @name LPTIM_CR register + * @{ + */ +#define STM32_LPTIM_CR_ENABLE (1U << 0) +#define STM32_LPTIM_CR_SNGSTRT (1U << 1) +#define STM32_LPTIM_CR_CNTSTRT (1U << 2) +/** @} */ + +/** + * @name LPTIM_OR register + * @{ + */ +#define STM32_LPTIM_OR_0 (1U << 0) +#define STM32_LPTIM_OR_1 (1U << 1) +/** @} */ + +/** + * @name TIM units references + * @{ + */ +#define STM32_TIM1 ((stm32_tim_t *)TIM1_BASE) +#define STM32_TIM2 ((stm32_tim_t *)TIM2_BASE) +#define STM32_TIM3 ((stm32_tim_t *)TIM3_BASE) +#define STM32_TIM4 ((stm32_tim_t *)TIM4_BASE) +#define STM32_TIM5 ((stm32_tim_t *)TIM5_BASE) +#define STM32_TIM6 ((stm32_tim_t *)TIM6_BASE) +#define STM32_TIM7 ((stm32_tim_t *)TIM7_BASE) +#define STM32_TIM8 ((stm32_tim_t *)TIM8_BASE) +#define STM32_TIM9 ((stm32_tim_t *)TIM9_BASE) +#define STM32_TIM10 ((stm32_tim_t *)TIM10_BASE) +#define STM32_TIM11 ((stm32_tim_t *)TIM11_BASE) +#define STM32_TIM12 ((stm32_tim_t *)TIM12_BASE) +#define STM32_TIM13 ((stm32_tim_t *)TIM13_BASE) +#define STM32_TIM14 ((stm32_tim_t *)TIM14_BASE) +#define STM32_TIM15 ((stm32_tim_t *)TIM15_BASE) +#define STM32_TIM16 ((stm32_tim_t *)TIM16_BASE) +#define STM32_TIM17 ((stm32_tim_t *)TIM17_BASE) +#define STM32_TIM18 ((stm32_tim_t *)TIM18_BASE) +#define STM32_TIM19 ((stm32_tim_t *)TIM19_BASE) +#define STM32_TIM20 ((stm32_tim_t *)TIM20_BASE) +#define STM32_TIM21 ((stm32_tim_t *)TIM21_BASE) +#define STM32_TIM22 ((stm32_tim_t *)TIM22_BASE) + +#define STM32_LPTIM1 ((stm32_lptim_t *)LPTIM1_BASE) +#define STM32_LPTIM2 ((stm32_lptim_t *)LPTIM2_BASE) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 TIM registers block. + * @note This is the most general known form, not all timers have + * necessarily all registers and bits. + */ +typedef struct { + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t SMCR; + volatile uint32_t DIER; + volatile uint32_t SR; + volatile uint32_t EGR; + volatile uint32_t CCMR1; + volatile uint32_t CCMR2; + volatile uint32_t CCER; + volatile uint32_t CNT; + volatile uint32_t PSC; + volatile uint32_t ARR; + volatile uint32_t RCR; + volatile uint32_t CCR[4]; + volatile uint32_t BDTR; +#if defined(STM32G4) + volatile uint32_t CCXR[2]; + volatile uint32_t CCMR3; + volatile uint32_t DTR2; + volatile uint32_t ECR; + volatile uint32_t TISEL; + volatile uint32_t AF1; + volatile uint32_t AF2; + volatile uint32_t OR; + volatile uint32_t RESERVED0[220]; + volatile uint32_t DCR; + volatile uint32_t DMAR; +#else + volatile uint32_t DCR; + volatile uint32_t DMAR; + volatile uint32_t OR; + volatile uint32_t CCMR3; + volatile uint32_t CCXR[2]; +#endif +} stm32_tim_t; + +/** + * @brief STM32 LPTIM registers block. + * @note This is the most general known form, not all timers have + * necessarily all registers and bits. + */ +typedef struct { + volatile uint32_t ISR; + volatile uint32_t ICR; + volatile uint32_t IER; + volatile uint32_t CFGR; + volatile uint32_t CR; + volatile uint32_t CMP; + volatile uint32_t ARR; + volatile uint32_t CNT; + volatile uint32_t OR; +} stm32_lptim_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* STM32_TIM_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt b/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt index ed215722f8..802ad1f7a6 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt +++ b/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt @@ -1,14 +1,14 @@ -TIM units IRQ collisions mapping. - - 1B 1UP 1TC 1CC 2 3 4 5 6 7 8B 8UP 8TC 8CC 9 10 11 12 13 14 15 16 17 18 19 20 21 22 LP1 LP2 -F0xx 1---1 2---2 * * * * * * * * -F030 1---1 2---2 * * * * * -F1xx 1 2 3 * * * * * * * 1 2 3 -F100 1 2 3 * * * * * * * 1 2 3 -F3xx 1 2 3 * * * * * * * * * * 1 2 3 -F37x * * * * * * * * * * * * * * -F4xx 1 2 3 * * * * * * * 4 5 6 * 1 2 3 4 5 6 -F7xx 1 2 3 * * * * * * * 4 5 6 * 1 2 3 4 5 6 * -L0xx * * * * * * * -L1xx * * * * * * * * * -L4xx 1 2 3 * * * * * * * * * * * 1 2 3 * * +TIM units IRQ collisions mapping. + + 1B 1UP 1TC 1CC 2 3 4 5 6 7 8B 8UP 8TC 8CC 9 10 11 12 13 14 15 16 17 18 19 20 21 22 LP1 LP2 +F0xx 1---1 2---2 * * * * * * * * +F030 1---1 2---2 * * * * * +F1xx 1 2 3 * * * * * * * 1 2 3 +F100 1 2 3 * * * * * * * 1 2 3 +F3xx 1 2 3 * * * * * * * * * * 1 2 3 +F37x * * * * * * * * * * * * * * +F4xx 1 2 3 * * * * * * * 4 5 6 * 1 2 3 4 5 6 +F7xx 1 2 3 * * * * * * * 4 5 6 * 1 2 3 4 5 6 * +L0xx * * * * * * * +L1xx * * * * * * * * * +L4xx 1 2 3 * * * * * * * * * * * 1 2 3 * * diff --git a/os/hal/ports/STM32/LLD/USARTv1/driver.mk b/os/hal/ports/STM32/LLD/USARTv1/driver.mk index 2f65c1f1fb..4f46aebd5c 100644 --- a/os/hal/ports/STM32/LLD/USARTv1/driver.mk +++ b/os/hal/ports/STM32/LLD/USARTv1/driver.mk @@ -1,13 +1,13 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c -endif -ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c +endif +ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1 diff --git a/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c b/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c index 188740e5a3..8a8d856c64 100644 --- a/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c @@ -1,650 +1,650 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv1/hal_serial_lld.c - * @brief STM32 low level serial driver code. - * - * @addtogroup SERIAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -SerialDriver SD1; -#endif - -/** @brief USART2 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -SerialDriver SD2; -#endif - -/** @brief USART3 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -SerialDriver SD3; -#endif - -/** @brief UART4 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -SerialDriver SD4; -#endif - -/** @brief UART5 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -SerialDriver SD5; -#endif - -/** @brief USART6 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -SerialDriver SD6; -#endif - -/** @brief UART7 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -SerialDriver SD7; -#endif - -/** @brief UART8 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -SerialDriver SD8; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** @brief Driver default configuration.*/ -static const SerialConfig default_config = -{ - SERIAL_DEFAULT_BITRATE, - 0, - USART_CR2_STOP1_BITS, - 0 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration - */ -static void usart_init(SerialDriver *sdp, const SerialConfig *config) { - uint32_t fck; - USART_TypeDef *u = sdp->usart; - - /* Baud rate setting.*/ -#if STM32_HAS_USART6 - if ((sdp->usart == USART1) || (sdp->usart == USART6)) -#else - if (sdp->usart == USART1) -#endif - fck = STM32_PCLK2 / config->speed; - else - fck = STM32_PCLK1 / config->speed; - - /* Correcting USARTDIV when oversampling by 8 instead of 16. - Fraction is still 4 bits wide, but only lower 3 bits used. - Mantissa is doubled, but Fraction is left the same.*/ -#if defined(USART_CR1_OVER8) - if (config->cr1 & USART_CR1_OVER8) - fck = ((fck & ~7) * 2) | (fck & 7); -#endif - u->BRR = fck; - - /* Note that some bits are enforced.*/ - u->CR2 = config->cr2 | USART_CR2_LBDIE; - u->CR3 = config->cr3 | USART_CR3_EIE; - u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | - USART_CR1_RXNEIE | USART_CR1_TE | - USART_CR1_RE; - u->SR = 0; - (void)u->SR; /* SR reset step 1.*/ - (void)u->DR; /* SR reset step 2.*/ - - /* Deciding mask to be applied on the data register on receive, this is - required in order to mask out the parity bit.*/ - if ((config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_PCE) { - sdp->rxmask = 0x7F; - } - else { - sdp->rxmask = 0xFF; - } -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] u pointer to an USART I/O block - */ -static void usart_deinit(USART_TypeDef *u) { - - u->CR1 = 0; - u->CR2 = 0; - u->CR3 = 0; -} - -/** - * @brief Error handling routine. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] sr USART SR register value - */ -static void set_error(SerialDriver *sdp, uint16_t sr) { - eventflags_t sts = 0; - - if (sr & USART_SR_ORE) - sts |= SD_OVERRUN_ERROR; - if (sr & USART_SR_PE) - sts |= SD_PARITY_ERROR; - if (sr & USART_SR_FE) - sts |= SD_FRAMING_ERROR; - if (sr & USART_SR_NE) - sts |= SD_NOISE_ERROR; - chnAddFlagsI(sdp, sts); -} - -/** - * @brief Common IRQ handler. - * - * @param[in] sdp communication channel associated to the USART - */ -static void serve_interrupt(SerialDriver *sdp) { - USART_TypeDef *u = sdp->usart; - uint16_t cr1 = u->CR1; - uint16_t sr = u->SR; - - /* Special case, LIN break detection.*/ - if (sr & USART_SR_LBD) { - osalSysLockFromISR(); - chnAddFlagsI(sdp, SD_BREAK_DETECTED); - u->SR = ~USART_SR_LBD; - osalSysUnlockFromISR(); - } - - /* Data available.*/ - osalSysLockFromISR(); - while (sr & (USART_SR_RXNE | USART_SR_ORE | USART_SR_NE | USART_SR_FE | - USART_SR_PE)) { - uint8_t b; - - /* Error condition detection.*/ - if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) - set_error(sdp, sr); - b = (uint8_t)u->DR & sdp->rxmask; - if (sr & USART_SR_RXNE) - sdIncomingDataI(sdp, b); - sr = u->SR; - } - osalSysUnlockFromISR(); - - /* Transmission buffer empty.*/ - if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) { - msg_t b; - osalSysLockFromISR(); - b = oqGetI(&sdp->oqueue); - if (b < MSG_OK) { - chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); - u->CR1 = cr1 & ~USART_CR1_TXEIE; - } - else - u->DR = b; - osalSysUnlockFromISR(); - } - - /* Physical transmission end.*/ - if ((cr1 & USART_CR1_TCIE) && (sr & USART_SR_TC)) { - osalSysLockFromISR(); - if (oqIsEmptyI(&sdp->oqueue)) { - chnAddFlagsI(sdp, CHN_TRANSMISSION_END); - u->CR1 = cr1 & ~USART_CR1_TCIE; - } - osalSysUnlockFromISR(); - } -} - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -static void notify1(io_queue_t *qp) { - - (void)qp; - USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -static void notify2(io_queue_t *qp) { - - (void)qp; - USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -static void notify3(io_queue_t *qp) { - - (void)qp; - USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -static void notify4(io_queue_t *qp) { - - (void)qp; - UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -static void notify5(io_queue_t *qp) { - - (void)qp; - UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -static void notify6(io_queue_t *qp) { - - (void)qp; - USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -static void notify7(io_queue_t *qp) { - - (void)qp; - UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -static void notify8(io_queue_t *qp) { - - (void)qp; - UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART6 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -#if !defined(STM32_UART7_HANDLER) -#error "STM32_UART7_HANDLER not defined" -#endif -/** - * @brief UART7 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -#if !defined(STM32_UART8_HANDLER) -#error "STM32_UART8_HANDLER not defined" -#endif -/** - * @brief UART8 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level serial driver initialization. - * - * @notapi - */ -void sd_lld_init(void) { - -#if STM32_SERIAL_USE_USART1 - sdObjectInit(&SD1, NULL, notify1); - SD1.usart = USART1; -#endif - -#if STM32_SERIAL_USE_USART2 - sdObjectInit(&SD2, NULL, notify2); - SD2.usart = USART2; -#endif - -#if STM32_SERIAL_USE_USART3 - sdObjectInit(&SD3, NULL, notify3); - SD3.usart = USART3; -#endif - -#if STM32_SERIAL_USE_UART4 - sdObjectInit(&SD4, NULL, notify4); - SD4.usart = UART4; -#endif - -#if STM32_SERIAL_USE_UART5 - sdObjectInit(&SD5, NULL, notify5); - SD5.usart = UART5; -#endif - -#if STM32_SERIAL_USE_USART6 - sdObjectInit(&SD6, NULL, notify6); - SD6.usart = USART6; -#endif - -#if STM32_SERIAL_USE_UART7 - sdObjectInit(&SD7, NULL, notify7); - SD7.usart = UART7; -#endif - -#if STM32_SERIAL_USE_UART8 - sdObjectInit(&SD8, NULL, notify8); - SD8.usart = UART8; -#endif -} - -/** - * @brief Low level serial driver configuration and (re)start. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration. - * If this parameter is set to @p NULL then a default - * configuration is used. - * - * @notapi - */ -void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { - - if (config == NULL) - config = &default_config; - - if (sdp->state == SD_STOP) { -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccEnableUSART1(true); - nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccEnableUSART2(true); - nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccEnableUSART3(true); - nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccEnableUART4(true); - nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccEnableUART5(true); - nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccEnableUSART6(true); - nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART7 - if (&SD7 == sdp) { - rccEnableUART7(true); - nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART8 - if (&SD8 == sdp) { - rccEnableUART8(true); - nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY); - } -#endif - } - usart_init(sdp, config); -} - -/** - * @brief Low level serial driver stop. - * @details De-initializes the USART, stops the associated clock, resets the - * interrupt vector. - * - * @param[in] sdp pointer to a @p SerialDriver object - * - * @notapi - */ -void sd_lld_stop(SerialDriver *sdp) { - - if (sdp->state == SD_READY) { - usart_deinit(sdp->usart); -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccDisableUSART1(); - nvicDisableVector(STM32_USART1_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccDisableUSART2(); - nvicDisableVector(STM32_USART2_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccDisableUSART3(); - nvicDisableVector(STM32_USART3_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccDisableUART4(); - nvicDisableVector(STM32_UART4_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccDisableUART5(); - nvicDisableVector(STM32_UART5_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccDisableUSART6(); - nvicDisableVector(STM32_USART6_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART7 - if (&SD7 == sdp) { - rccDisableUART7(); - nvicDisableVector(STM32_UART7_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART8 - if (&SD8 == sdp) { - rccDisableUART8(); - nvicDisableVector(STM32_UART8_NUMBER); - return; - } -#endif - } -} - -#endif /* HAL_USE_SERIAL */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv1/hal_serial_lld.c + * @brief STM32 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +/** @brief USART2 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +/** @brief USART3 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +SerialDriver SD3; +#endif + +/** @brief UART4 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +/** @brief UART5 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +/** @brief USART6 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + +/** @brief UART7 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +SerialDriver SD7; +#endif + +/** @brief UART8 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +SerialDriver SD8; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** @brief Driver default configuration.*/ +static const SerialConfig default_config = +{ + SERIAL_DEFAULT_BITRATE, + 0, + USART_CR2_STOP1_BITS, + 0 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration + */ +static void usart_init(SerialDriver *sdp, const SerialConfig *config) { + uint32_t fck; + USART_TypeDef *u = sdp->usart; + + /* Baud rate setting.*/ +#if STM32_HAS_USART6 + if ((sdp->usart == USART1) || (sdp->usart == USART6)) +#else + if (sdp->usart == USART1) +#endif + fck = STM32_PCLK2 / config->speed; + else + fck = STM32_PCLK1 / config->speed; + + /* Correcting USARTDIV when oversampling by 8 instead of 16. + Fraction is still 4 bits wide, but only lower 3 bits used. + Mantissa is doubled, but Fraction is left the same.*/ +#if defined(USART_CR1_OVER8) + if (config->cr1 & USART_CR1_OVER8) + fck = ((fck & ~7) * 2) | (fck & 7); +#endif + u->BRR = fck; + + /* Note that some bits are enforced.*/ + u->CR2 = config->cr2 | USART_CR2_LBDIE; + u->CR3 = config->cr3 | USART_CR3_EIE; + u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | + USART_CR1_RXNEIE | USART_CR1_TE | + USART_CR1_RE; + u->SR = 0; + (void)u->SR; /* SR reset step 1.*/ + (void)u->DR; /* SR reset step 2.*/ + + /* Deciding mask to be applied on the data register on receive, this is + required in order to mask out the parity bit.*/ + if ((config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_PCE) { + sdp->rxmask = 0x7F; + } + else { + sdp->rxmask = 0xFF; + } +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] u pointer to an USART I/O block + */ +static void usart_deinit(USART_TypeDef *u) { + + u->CR1 = 0; + u->CR2 = 0; + u->CR3 = 0; +} + +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] sr USART SR register value + */ +static void set_error(SerialDriver *sdp, uint16_t sr) { + eventflags_t sts = 0; + + if (sr & USART_SR_ORE) + sts |= SD_OVERRUN_ERROR; + if (sr & USART_SR_PE) + sts |= SD_PARITY_ERROR; + if (sr & USART_SR_FE) + sts |= SD_FRAMING_ERROR; + if (sr & USART_SR_NE) + sts |= SD_NOISE_ERROR; + chnAddFlagsI(sdp, sts); +} + +/** + * @brief Common IRQ handler. + * + * @param[in] sdp communication channel associated to the USART + */ +static void serve_interrupt(SerialDriver *sdp) { + USART_TypeDef *u = sdp->usart; + uint16_t cr1 = u->CR1; + uint16_t sr = u->SR; + + /* Special case, LIN break detection.*/ + if (sr & USART_SR_LBD) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, SD_BREAK_DETECTED); + u->SR = ~USART_SR_LBD; + osalSysUnlockFromISR(); + } + + /* Data available.*/ + osalSysLockFromISR(); + while (sr & (USART_SR_RXNE | USART_SR_ORE | USART_SR_NE | USART_SR_FE | + USART_SR_PE)) { + uint8_t b; + + /* Error condition detection.*/ + if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) + set_error(sdp, sr); + b = (uint8_t)u->DR & sdp->rxmask; + if (sr & USART_SR_RXNE) + sdIncomingDataI(sdp, b); + sr = u->SR; + } + osalSysUnlockFromISR(); + + /* Transmission buffer empty.*/ + if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) { + msg_t b; + osalSysLockFromISR(); + b = oqGetI(&sdp->oqueue); + if (b < MSG_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + u->CR1 = cr1 & ~USART_CR1_TXEIE; + } + else + u->DR = b; + osalSysUnlockFromISR(); + } + + /* Physical transmission end.*/ + if ((cr1 & USART_CR1_TCIE) && (sr & USART_SR_TC)) { + osalSysLockFromISR(); + if (oqIsEmptyI(&sdp->oqueue)) { + chnAddFlagsI(sdp, CHN_TRANSMISSION_END); + u->CR1 = cr1 & ~USART_CR1_TCIE; + } + osalSysUnlockFromISR(); + } +} + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +static void notify1(io_queue_t *qp) { + + (void)qp; + USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +static void notify2(io_queue_t *qp) { + + (void)qp; + USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +static void notify3(io_queue_t *qp) { + + (void)qp; + USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +static void notify4(io_queue_t *qp) { + + (void)qp; + UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +static void notify5(io_queue_t *qp) { + + (void)qp; + UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +static void notify6(io_queue_t *qp) { + + (void)qp; + USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +static void notify7(io_queue_t *qp) { + + (void)qp; + UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +static void notify8(io_queue_t *qp) { + + (void)qp; + UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +#if !defined(STM32_UART7_HANDLER) +#error "STM32_UART7_HANDLER not defined" +#endif +/** + * @brief UART7 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +#if !defined(STM32_UART8_HANDLER) +#error "STM32_UART8_HANDLER not defined" +#endif +/** + * @brief UART8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if STM32_SERIAL_USE_USART1 + sdObjectInit(&SD1, NULL, notify1); + SD1.usart = USART1; +#endif + +#if STM32_SERIAL_USE_USART2 + sdObjectInit(&SD2, NULL, notify2); + SD2.usart = USART2; +#endif + +#if STM32_SERIAL_USE_USART3 + sdObjectInit(&SD3, NULL, notify3); + SD3.usart = USART3; +#endif + +#if STM32_SERIAL_USE_UART4 + sdObjectInit(&SD4, NULL, notify4); + SD4.usart = UART4; +#endif + +#if STM32_SERIAL_USE_UART5 + sdObjectInit(&SD5, NULL, notify5); + SD5.usart = UART5; +#endif + +#if STM32_SERIAL_USE_USART6 + sdObjectInit(&SD6, NULL, notify6); + SD6.usart = USART6; +#endif + +#if STM32_SERIAL_USE_UART7 + sdObjectInit(&SD7, NULL, notify7); + SD7.usart = UART7; +#endif + +#if STM32_SERIAL_USE_UART8 + sdObjectInit(&SD8, NULL, notify8); + SD8.usart = UART8; +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) + config = &default_config; + + if (sdp->state == SD_STOP) { +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccEnableUSART1(true); + nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccEnableUSART2(true); + nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccEnableUSART3(true); + nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccEnableUART4(true); + nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccEnableUART5(true); + nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccEnableUSART6(true); + nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART7 + if (&SD7 == sdp) { + rccEnableUART7(true); + nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART8 + if (&SD8 == sdp) { + rccEnableUART8(true); + nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY); + } +#endif + } + usart_init(sdp, config); +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { + usart_deinit(sdp->usart); +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccDisableUSART1(); + nvicDisableVector(STM32_USART1_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccDisableUSART2(); + nvicDisableVector(STM32_USART2_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccDisableUSART3(); + nvicDisableVector(STM32_USART3_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccDisableUART4(); + nvicDisableVector(STM32_UART4_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccDisableUART5(); + nvicDisableVector(STM32_UART5_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccDisableUSART6(); + nvicDisableVector(STM32_USART6_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART7 + if (&SD7 == sdp) { + rccDisableUART7(); + nvicDisableVector(STM32_UART7_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART8 + if (&SD8 == sdp) { + rccDisableUART8(); + nvicDisableVector(STM32_UART8_NUMBER); + return; + } +#endif + } +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h b/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h index de259a70d3..4b40942266 100644 --- a/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h @@ -1,362 +1,362 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv1/hal_serial_lld.h - * @brief STM32 low level serial driver header. - * - * @addtogroup SERIAL - * @{ - */ - -#ifndef HAL_SERIAL_LLD_H -#define HAL_SERIAL_LLD_H - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief USART1 driver enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART1 FALSE -#endif - -/** - * @brief USART2 driver enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART2 FALSE -#endif - -/** - * @brief USART3 driver enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART3 FALSE -#endif - -/** - * @brief UART4 driver enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART4 FALSE -#endif - -/** - * @brief UART5 driver enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART5 FALSE -#endif - -/** - * @brief USART6 driver enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART6 FALSE -#endif - -/** - * @brief UART7 driver enable switch. - * @details If set to @p TRUE the support for UART7 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART7 FALSE -#endif - -/** - * @brief UART8 driver enable switch. - * @details If set to @p TRUE the support for UART8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART8 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART1_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART2_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART3_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART4_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART5_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART6_PRIORITY 12 -#endif - -/** - * @brief UART7 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART7_PRIORITY 12 -#endif - -/** - * @brief UART8 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART8_PRIORITY 12 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 -#error "UART4 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 -#error "UART5 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 -#error "USART6 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7 -#error "UART7 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8 -#error "UART8 not present in the selected device" -#endif - -#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ - !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ - !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \ - !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8 -#error "SERIAL driver activated but no USART/UART peripheral assigned" -#endif - -#if STM32_SERIAL_USE_USART1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if STM32_SERIAL_USE_USART2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if STM32_SERIAL_USE_USART3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if STM32_SERIAL_USE_UART4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if STM32_SERIAL_USE_UART5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if STM32_SERIAL_USE_USART6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -#if STM32_SERIAL_USE_UART7 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY) -#error "Invalid IRQ priority assigned to UART7" -#endif - -#if STM32_SERIAL_USE_UART8 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY) -#error "Invalid IRQ priority assigned to UART8" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 Serial Driver configuration structure. - * @details An instance of this structure must be passed to @p sdStart() - * in order to configure and start a serial driver operations. - * @note This structure content is architecture dependent, each driver - * implementation defines its own version and the custom static - * initializers. - */ -typedef struct { - /** - * @brief Bit rate. - */ - uint32_t speed; - /* End of the mandatory fields.*/ - /** - * @brief Initialization value for the CR1 register. - */ - uint16_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint16_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint16_t cr3; -} SerialConfig; - -/** - * @brief @p SerialDriver specific data. - */ -#define _serial_driver_data \ - _base_asynchronous_channel_data \ - /* Driver state.*/ \ - sdstate_t state; \ - /* Input queue.*/ \ - input_queue_t iqueue; \ - /* Output queue.*/ \ - output_queue_t oqueue; \ - /* Input circular buffer.*/ \ - uint8_t ib[SERIAL_BUFFERS_SIZE]; \ - /* Output circular buffer.*/ \ - uint8_t ob[SERIAL_BUFFERS_SIZE]; \ - /* End of the mandatory fields.*/ \ - /* Pointer to the USART registers block.*/ \ - USART_TypeDef *usart; \ - /* Mask to be applied on received frames.*/ \ - uint8_t rxmask; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/* - * Extra USARTs definitions here (missing from the ST header file). - */ -#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ -#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ -#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ -#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) -extern SerialDriver SD1; -#endif -#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) -extern SerialDriver SD2; -#endif -#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) -extern SerialDriver SD3; -#endif -#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) -extern SerialDriver SD4; -#endif -#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) -extern SerialDriver SD5; -#endif -#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) -extern SerialDriver SD6; -#endif -#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__) -extern SerialDriver SD7; -#endif -#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__) -extern SerialDriver SD8; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sd_lld_init(void); - void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); - void sd_lld_stop(SerialDriver *sdp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SERIAL */ - -#endif /* HAL_SERIAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv1/hal_serial_lld.h + * @brief STM32 low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef HAL_SERIAL_LLD_H +#define HAL_SERIAL_LLD_H + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART1 FALSE +#endif + +/** + * @brief USART2 driver enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART2 FALSE +#endif + +/** + * @brief USART3 driver enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART3 FALSE +#endif + +/** + * @brief UART4 driver enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART4 FALSE +#endif + +/** + * @brief UART5 driver enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief USART6 driver enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART6 FALSE +#endif + +/** + * @brief UART7 driver enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART7 FALSE +#endif + +/** + * @brief UART8 driver enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART8 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_PRIORITY 12 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_PRIORITY 12 +#endif + +/** + * @brief UART8 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_PRIORITY 12 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7 +#error "UART7 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8 +#error "UART8 not present in the selected device" +#endif + +#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ + !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ + !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \ + !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8 +#error "SERIAL driver activated but no USART/UART peripheral assigned" +#endif + +#if STM32_SERIAL_USE_USART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if STM32_SERIAL_USE_USART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if STM32_SERIAL_USE_USART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if STM32_SERIAL_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if STM32_SERIAL_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if STM32_SERIAL_USE_USART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if STM32_SERIAL_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +#if STM32_SERIAL_USE_UART8 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY) +#error "Invalid IRQ priority assigned to UART8" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t speed; + /* End of the mandatory fields.*/ + /** + * @brief Initialization value for the CR1 register. + */ + uint16_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint16_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint16_t cr3; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* Input circular buffer.*/ \ + uint8_t ib[SERIAL_BUFFERS_SIZE]; \ + /* Output circular buffer.*/ \ + uint8_t ob[SERIAL_BUFFERS_SIZE]; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the USART registers block.*/ \ + USART_TypeDef *usart; \ + /* Mask to be applied on received frames.*/ \ + uint8_t rxmask; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * Extra USARTs definitions here (missing from the ST header file). + */ +#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ +#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ +#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ +#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif +#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif +#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif +#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif +#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif +#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__) +extern SerialDriver SD7; +#endif +#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__) +extern SerialDriver SD8; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* HAL_SERIAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c b/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c index a41a557461..919bd978ec 100644 --- a/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c @@ -1,1028 +1,1028 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv1/hal_uart_lld.c - * @brief STM32 low level UART driver code. - * - * @addtogroup UART - * @{ - */ - -#include "hal.h" - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define USART1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_CHN) - -#define USART1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_CHN) - -#define USART2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_CHN) - -#define USART2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_CHN) - -#define USART3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_CHN) - -#define USART3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_CHN) - -#define UART4_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ - STM32_UART4_RX_DMA_CHN) - -#define UART4_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ - STM32_UART4_TX_DMA_CHN) - -#define UART5_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ - STM32_UART5_RX_DMA_CHN) - -#define UART5_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ - STM32_UART5_TX_DMA_CHN) - -#define USART6_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ - STM32_USART6_RX_DMA_CHN) - -#define USART6_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ - STM32_USART6_TX_DMA_CHN) - -#define UART7_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \ - STM32_UART7_RX_DMA_CHN) - -#define UART7_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \ - STM32_UART7_TX_DMA_CHN) - -#define UART8_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \ - STM32_UART8_RX_DMA_CHN) - -#define UART8_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \ - STM32_UART8_TX_DMA_CHN) - -#define STM32_UART45_CR2_CHECK_MASK \ - (USART_CR2_STOP_0 | USART_CR2_CLKEN | USART_CR2_CPOL | USART_CR2_CPHA | \ - USART_CR2_LBCL) - -#define STM32_UART45_CR3_CHECK_MASK \ - (USART_CR3_CTSIE | USART_CR3_CTSE | USART_CR3_RTSE | USART_CR3_SCEN | \ - USART_CR3_NACK) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 UART driver identifier.*/ -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -UARTDriver UARTD1; -#endif - -/** @brief USART2 UART driver identifier.*/ -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -UARTDriver UARTD2; -#endif - -/** @brief USART3 UART driver identifier.*/ -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -UARTDriver UARTD3; -#endif - -/** @brief UART4 UART driver identifier.*/ -#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) -UARTDriver UARTD4; -#endif - -/** @brief UART5 UART driver identifier.*/ -#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) -UARTDriver UARTD5; -#endif - -/** @brief USART6 UART driver identifier.*/ -#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) -UARTDriver UARTD6; -#endif - -/** @brief UART7 UART driver identifier.*/ -#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) -UARTDriver UARTD7; -#endif - -/** @brief UART8 UART driver identifier.*/ -#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) -UARTDriver UARTD8; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Status bits translation. - * - * @param[in] sr USART SR register value - * - * @return The error flags. - */ -static uartflags_t translate_errors(uint16_t sr) { - uartflags_t sts = 0; - - if (sr & USART_SR_ORE) - sts |= UART_OVERRUN_ERROR; - if (sr & USART_SR_PE) - sts |= UART_PARITY_ERROR; - if (sr & USART_SR_FE) - sts |= UART_FRAMING_ERROR; - if (sr & USART_SR_NE) - sts |= UART_NOISE_ERROR; - if (sr & USART_SR_LBD) - sts |= UART_BREAK_DETECTED; - return sts; -} - -/** - * @brief Puts the receiver in the UART_RX_IDLE state. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void uart_enter_rx_idle_loop(UARTDriver *uartp) { - uint32_t mode; - - /* RX DMA channel preparation, if the char callback is defined then the - TCIE interrupt is enabled too.*/ - if (uartp->config->rxchar_cb == NULL) - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; - else - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; - dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, 1); - dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_stop(UARTDriver *uartp) { - - /* Stops RX and TX DMA channels.*/ - dmaStreamDisable(uartp->dmarx); - dmaStreamDisable(uartp->dmatx); - - /* Stops USART operations.*/ - uartp->usart->CR1 = 0; - uartp->usart->CR2 = 0; - uartp->usart->CR3 = 0; -} - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_start(UARTDriver *uartp) { - uint32_t fck; - uint16_t cr1; - USART_TypeDef *u = uartp->usart; - - /* Defensive programming, starting from a clean state.*/ - usart_stop(uartp); - - /* Baud rate setting.*/ -#if STM32_HAS_USART6 - if ((uartp->usart == USART1) || (uartp->usart == USART6)) -#else - if (uartp->usart == USART1) -#endif - fck = STM32_PCLK2 / uartp->config->speed; - else - fck = STM32_PCLK1 / uartp->config->speed; - - /* Correcting USARTDIV when oversampling by 8 instead of 16. - Fraction is still 4 bits wide, but only lower 3 bits used. - Mantissa is doubled, but Fraction is left the same.*/ -#if defined(USART_CR1_OVER8) - if (uartp->config->cr1 & USART_CR1_OVER8) - fck = ((fck & ~7) * 2) | (fck & 7); -#endif - u->BRR = fck; - - /* Resetting eventual pending status flags.*/ - (void)u->SR; /* SR reset step 1.*/ - (void)u->DR; /* SR reset step 2.*/ - u->SR = 0; - - /* Note that some bits are enforced because required for correct driver - operations.*/ - u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; - u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | - USART_CR3_EIE; - - /* Mustn't ever set TCIE here - if done, it causes an immediate - interrupt.*/ - cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; - - /* Add Idle interrupt if needed */ - if (uartp->config->timeout_cb != NULL) - cr1 |= USART_CR1_IDLEIE; - - u->CR1 = uartp->config->cr1 | cr1; - - /* Starting the receiver idle loop.*/ - uart_enter_rx_idle_loop(uartp); -} - -/** - * @brief RX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - if (uartp->rxstate == UART_RX_IDLE) { - /* Receiver in idle state, a callback is generated, if enabled, for each - received character and then the driver stays in the same state.*/ - _uart_rx_idle_code(uartp); - } - /* DMA half-transter interrupt handling - for the 1st/2nd half transfers. */ - else if (uartp->config->rxhalf_cb != NULL) { - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - _uart_rx_half_isr_code(uartp, 0); - } - else if ((flags & STM32_DMA_ISR_TCIF) != 0) { - _uart_rx_half_isr_code(uartp, 1); - } - } - else { - /* Receiver in active state, a callback is generated, if enabled, after - a completed transfer.*/ - dmaStreamDisable(uartp->dmarx); - _uart_rx_complete_isr_code(uartp); - } -} - -/** - * @brief TX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(uartp->dmatx); - - /* A callback is generated, if enabled, after a completed transfer.*/ - _uart_tx1_isr_code(uartp); -} - -/** - * @brief USART common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void serve_usart_irq(UARTDriver *uartp) { - uint16_t sr; - USART_TypeDef *u = uartp->usart; - uint32_t cr1 = u->CR1; - - sr = u->SR; /* SR reset step 1.*/ - (void)u->DR; /* SR reset step 2.*/ - - if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE | - USART_SR_FE | USART_SR_PE)) { - u->SR = ~USART_SR_LBD; - _uart_rx_error_isr_code(uartp, translate_errors(sr)); - } - - if ((sr & USART_SR_TC) && (cr1 & USART_CR1_TCIE)) { - /* TC interrupt cleared and disabled.*/ - u->SR = ~USART_SR_TC; - u->CR1 = cr1 & ~USART_CR1_TCIE; - - /* End of transmission, a callback is generated.*/ - _uart_tx2_isr_code(uartp); - } - - /* Timeout interrupt sources are only checked if enabled in CR1.*/ - if ((cr1 & USART_CR1_IDLEIE) && (sr & USART_SR_IDLE)) { - _uart_timeout_isr_code(uartp); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART1 */ - -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART2 */ - -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART3 */ - -#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_UART4 */ - -#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_UART5 */ - -#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART6 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART6 */ - -#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) -#if !defined(STM32_UART7_HANDLER) -#error "STM32_UART7_HANDLER not defined" -#endif -/** - * @brief UART7 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_UART7 */ - -#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) -#if !defined(STM32_UART8_HANDLER) -#error "STM32_UART8_HANDLER not defined" -#endif -/** - * @brief UART8 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_UART8 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level UART driver initialization. - * - * @notapi - */ -void uart_lld_init(void) { - -#if STM32_UART_USE_USART1 - uartObjectInit(&UARTD1); - UARTD1.usart = USART1; - UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD1.dmarx = NULL; - UARTD1.dmatx = NULL; -#endif - -#if STM32_UART_USE_USART2 - uartObjectInit(&UARTD2); - UARTD2.usart = USART2; - UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD2.dmarx = NULL; - UARTD2.dmatx = NULL; -#endif - -#if STM32_UART_USE_USART3 - uartObjectInit(&UARTD3); - UARTD3.usart = USART3; - UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD3.dmarx = NULL; - UARTD3.dmatx = NULL; -#endif - -#if STM32_UART_USE_UART4 - uartObjectInit(&UARTD4); - UARTD4.usart = UART4; - UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD4.dmarx = NULL; - UARTD4.dmatx = NULL; -#endif - -#if STM32_UART_USE_UART5 - uartObjectInit(&UARTD5); - UARTD5.usart = UART5; - UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD5.dmarx = NULL; - UARTD5.dmatx = NULL; -#endif - -#if STM32_UART_USE_USART6 - uartObjectInit(&UARTD6); - UARTD6.usart = USART6; - UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD6.dmarx = NULL; - UARTD6.dmatx = NULL; -#endif - -#if STM32_UART_USE_UART7 - uartObjectInit(&UARTD7); - UARTD7.usart = UART7; - UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD7.dmarx = NULL; - UARTD7.dmatx = NULL; -#endif - -#if STM32_UART_USE_UART8 - uartObjectInit(&UARTD8); - UARTD8.usart = UART8; - UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD8.dmarx = NULL; - UARTD8.dmatx = NULL; -#endif -} - -/** - * @brief Configures and activates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_start(UARTDriver *uartp) { - - if (uartp->state == UART_STOP) { -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART1(true); - nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART2(true); - nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART3(true); - nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_UART4 - if (&UARTD4 == uartp) { - - osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, - "specified invalid bits in UART4 CR2 register settings"); - osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, - "specified invalid bits in UART4 CR3 register settings"); - - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM, - STM32_UART_UART4_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM, - STM32_UART_UART4_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART4(true); - nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_UART5 - if (&UARTD5 == uartp) { - - osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, - "specified invalid bits in UART5 CR2 register settings"); - osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, - "specified invalid bits in UART5 CR3 register settings"); - - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM, - STM32_UART_UART5_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM, - STM32_UART_UART5_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART5(true); - nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART6 - if (&UARTD6 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM, - STM32_UART_USART6_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM, - STM32_UART_USART6_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART6(true); - nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_UART7 - if (&UARTD7 == uartp) { - - osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, - "specified invalid bits in UART7 CR2 register settings"); - osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, - "specified invalid bits in UART7 CR3 register settings"); - - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM, - STM32_UART_UART7_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM, - STM32_UART_UART7_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART7(true); - nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_UART8 - if (&UARTD8 == uartp) { - - osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, - "specified invalid bits in UART8 CR2 register settings"); - osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, - "specified invalid bits in UART8 CR3 register settings"); - - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM, - STM32_UART_UART8_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM, - STM32_UART_UART8_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART8(true); - nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); - } -#endif - - /* Static DMA setup, the transfer size depends on the USART settings, - it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ - if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) { - uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DR); - dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DR); - uartp->rxbuf = 0; - } - - uartp->rxstate = UART_RX_IDLE; - uartp->txstate = UART_TX_IDLE; - usart_start(uartp); -} - -/** - * @brief Deactivates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_stop(UARTDriver *uartp) { - - if (uartp->state == UART_READY) { - usart_stop(uartp); - dmaStreamFreeI(uartp->dmarx); - dmaStreamFreeI(uartp->dmatx); - uartp->dmarx = NULL; - uartp->dmatx = NULL; - -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - nvicDisableVector(STM32_USART1_NUMBER); - rccDisableUSART1(); - return; - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - nvicDisableVector(STM32_USART2_NUMBER); - rccDisableUSART2(); - return; - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - nvicDisableVector(STM32_USART3_NUMBER); - rccDisableUSART3(); - return; - } -#endif - -#if STM32_UART_USE_UART4 - if (&UARTD4 == uartp) { - nvicDisableVector(STM32_UART4_NUMBER); - rccDisableUART4(); - return; - } -#endif - -#if STM32_UART_USE_UART5 - if (&UARTD5 == uartp) { - nvicDisableVector(STM32_UART5_NUMBER); - rccDisableUART5(); - return; - } -#endif - -#if STM32_UART_USE_USART6 - if (&UARTD6 == uartp) { - nvicDisableVector(STM32_USART6_NUMBER); - rccDisableUSART6(); - return; - } -#endif - -#if STM32_UART_USE_UART7 - if (&UARTD7 == uartp) { - nvicDisableVector(STM32_UART7_NUMBER); - rccDisableUART7(); - return; - } -#endif - -#if STM32_UART_USE_UART8 - if (&UARTD8 == uartp) { - nvicDisableVector(STM32_UART8_NUMBER); - rccDisableUART8(); - return; - } -#endif - } -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { - - /* TX DMA channel preparation.*/ - dmaStreamSetMemory0(uartp->dmatx, txbuf); - dmaStreamSetTransactionSize(uartp->dmatx, n); - dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - - /* Only enable TC interrupt if there's a callback attached to it or - if called from uartSendFullTimeout(). Also we need to clear TC flag - which could be set before.*/ -#if UART_USE_WAIT == TRUE - if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) { -#else - if (uartp->config->txend2_cb != NULL) { -#endif - uartp->usart->SR = ~USART_SR_TC; - uartp->usart->CR1 |= USART_CR1_TCIE; - } - - /* Starting transfer.*/ - dmaStreamEnable(uartp->dmatx); -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * - * @notapi - */ -size_t uart_lld_stop_send(UARTDriver *uartp) { - - dmaStreamDisable(uartp->dmatx); - - return dmaStreamGetTransactionSize(uartp->dmatx); -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { - - /* Stopping previous activity (idle state).*/ - dmaStreamDisable(uartp->dmarx); - - /* RX DMA channel preparation.*/ - dmaStreamSetMemory0(uartp->dmarx, rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, n); - - uint32_t mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE; - - /* DMA half-transfer interrupt & circular mode, if needed */ - if (uartp->config->rxhalf_cb != NULL) - mode |= STM32_DMA_CR_HTIE | STM32_DMA_CR_CIRC; - - dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); - - /* Starting transfer.*/ - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * - * @notapi - */ -size_t uart_lld_stop_receive(UARTDriver *uartp) { - size_t n; - - dmaStreamDisable(uartp->dmarx); - n = dmaStreamGetTransactionSize(uartp->dmarx); - uart_enter_rx_idle_loop(uartp); - - return n; -} - -#endif /* HAL_USE_UART */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv1/hal_uart_lld.c + * @brief STM32 low level UART driver code. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define USART1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_CHN) + +#define USART1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_CHN) + +#define USART2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_CHN) + +#define USART2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_CHN) + +#define USART3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_CHN) + +#define USART3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_CHN) + +#define UART4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_CHN) + +#define UART4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_CHN) + +#define UART5_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_CHN) + +#define UART5_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_CHN) + +#define USART6_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_CHN) + +#define USART6_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_CHN) + +#define UART7_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \ + STM32_UART7_RX_DMA_CHN) + +#define UART7_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \ + STM32_UART7_TX_DMA_CHN) + +#define UART8_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \ + STM32_UART8_RX_DMA_CHN) + +#define UART8_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \ + STM32_UART8_TX_DMA_CHN) + +#define STM32_UART45_CR2_CHECK_MASK \ + (USART_CR2_STOP_0 | USART_CR2_CLKEN | USART_CR2_CPOL | USART_CR2_CPHA | \ + USART_CR2_LBCL) + +#define STM32_UART45_CR3_CHECK_MASK \ + (USART_CR3_CTSIE | USART_CR3_CTSE | USART_CR3_RTSE | USART_CR3_SCEN | \ + USART_CR3_NACK) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 UART driver identifier.*/ +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +UARTDriver UARTD1; +#endif + +/** @brief USART2 UART driver identifier.*/ +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +UARTDriver UARTD2; +#endif + +/** @brief USART3 UART driver identifier.*/ +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +UARTDriver UARTD3; +#endif + +/** @brief UART4 UART driver identifier.*/ +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +UARTDriver UARTD4; +#endif + +/** @brief UART5 UART driver identifier.*/ +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +UARTDriver UARTD5; +#endif + +/** @brief USART6 UART driver identifier.*/ +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +UARTDriver UARTD6; +#endif + +/** @brief UART7 UART driver identifier.*/ +#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) +UARTDriver UARTD7; +#endif + +/** @brief UART8 UART driver identifier.*/ +#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) +UARTDriver UARTD8; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Status bits translation. + * + * @param[in] sr USART SR register value + * + * @return The error flags. + */ +static uartflags_t translate_errors(uint16_t sr) { + uartflags_t sts = 0; + + if (sr & USART_SR_ORE) + sts |= UART_OVERRUN_ERROR; + if (sr & USART_SR_PE) + sts |= UART_PARITY_ERROR; + if (sr & USART_SR_FE) + sts |= UART_FRAMING_ERROR; + if (sr & USART_SR_NE) + sts |= UART_NOISE_ERROR; + if (sr & USART_SR_LBD) + sts |= UART_BREAK_DETECTED; + return sts; +} + +/** + * @brief Puts the receiver in the UART_RX_IDLE state. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void uart_enter_rx_idle_loop(UARTDriver *uartp) { + uint32_t mode; + + /* RX DMA channel preparation, if the char callback is defined then the + TCIE interrupt is enabled too.*/ + if (uartp->config->rxchar_cb == NULL) + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; + else + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; + dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, 1); + dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_stop(UARTDriver *uartp) { + + /* Stops RX and TX DMA channels.*/ + dmaStreamDisable(uartp->dmarx); + dmaStreamDisable(uartp->dmatx); + + /* Stops USART operations.*/ + uartp->usart->CR1 = 0; + uartp->usart->CR2 = 0; + uartp->usart->CR3 = 0; +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_start(UARTDriver *uartp) { + uint32_t fck; + uint16_t cr1; + USART_TypeDef *u = uartp->usart; + + /* Defensive programming, starting from a clean state.*/ + usart_stop(uartp); + + /* Baud rate setting.*/ +#if STM32_HAS_USART6 + if ((uartp->usart == USART1) || (uartp->usart == USART6)) +#else + if (uartp->usart == USART1) +#endif + fck = STM32_PCLK2 / uartp->config->speed; + else + fck = STM32_PCLK1 / uartp->config->speed; + + /* Correcting USARTDIV when oversampling by 8 instead of 16. + Fraction is still 4 bits wide, but only lower 3 bits used. + Mantissa is doubled, but Fraction is left the same.*/ +#if defined(USART_CR1_OVER8) + if (uartp->config->cr1 & USART_CR1_OVER8) + fck = ((fck & ~7) * 2) | (fck & 7); +#endif + u->BRR = fck; + + /* Resetting eventual pending status flags.*/ + (void)u->SR; /* SR reset step 1.*/ + (void)u->DR; /* SR reset step 2.*/ + u->SR = 0; + + /* Note that some bits are enforced because required for correct driver + operations.*/ + u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; + u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | + USART_CR3_EIE; + + /* Mustn't ever set TCIE here - if done, it causes an immediate + interrupt.*/ + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; + + /* Add Idle interrupt if needed */ + if (uartp->config->timeout_cb != NULL) + cr1 |= USART_CR1_IDLEIE; + + u->CR1 = uartp->config->cr1 | cr1; + + /* Starting the receiver idle loop.*/ + uart_enter_rx_idle_loop(uartp); +} + +/** + * @brief RX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + if (uartp->rxstate == UART_RX_IDLE) { + /* Receiver in idle state, a callback is generated, if enabled, for each + received character and then the driver stays in the same state.*/ + _uart_rx_idle_code(uartp); + } + /* DMA half-transter interrupt handling - for the 1st/2nd half transfers. */ + else if (uartp->config->rxhalf_cb != NULL) { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + _uart_rx_half_isr_code(uartp, 0); + } + else if ((flags & STM32_DMA_ISR_TCIF) != 0) { + _uart_rx_half_isr_code(uartp, 1); + } + } + else { + /* Receiver in active state, a callback is generated, if enabled, after + a completed transfer.*/ + dmaStreamDisable(uartp->dmarx); + _uart_rx_complete_isr_code(uartp); + } +} + +/** + * @brief TX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(uartp->dmatx); + + /* A callback is generated, if enabled, after a completed transfer.*/ + _uart_tx1_isr_code(uartp); +} + +/** + * @brief USART common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void serve_usart_irq(UARTDriver *uartp) { + uint16_t sr; + USART_TypeDef *u = uartp->usart; + uint32_t cr1 = u->CR1; + + sr = u->SR; /* SR reset step 1.*/ + (void)u->DR; /* SR reset step 2.*/ + + if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE | + USART_SR_FE | USART_SR_PE)) { + u->SR = ~USART_SR_LBD; + _uart_rx_error_isr_code(uartp, translate_errors(sr)); + } + + if ((sr & USART_SR_TC) && (cr1 & USART_CR1_TCIE)) { + /* TC interrupt cleared and disabled.*/ + u->SR = ~USART_SR_TC; + u->CR1 = cr1 & ~USART_CR1_TCIE; + + /* End of transmission, a callback is generated.*/ + _uart_tx2_isr_code(uartp); + } + + /* Timeout interrupt sources are only checked if enabled in CR1.*/ + if ((cr1 & USART_CR1_IDLEIE) && (sr & USART_SR_IDLE)) { + _uart_timeout_isr_code(uartp); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART1 */ + +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART2 */ + +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART3 */ + +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_UART4 */ + +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_UART5 */ + +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART6 */ + +#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) +#if !defined(STM32_UART7_HANDLER) +#error "STM32_UART7_HANDLER not defined" +#endif +/** + * @brief UART7 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_UART7 */ + +#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) +#if !defined(STM32_UART8_HANDLER) +#error "STM32_UART8_HANDLER not defined" +#endif +/** + * @brief UART8 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_UART8 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level UART driver initialization. + * + * @notapi + */ +void uart_lld_init(void) { + +#if STM32_UART_USE_USART1 + uartObjectInit(&UARTD1); + UARTD1.usart = USART1; + UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmarx = NULL; + UARTD1.dmatx = NULL; +#endif + +#if STM32_UART_USE_USART2 + uartObjectInit(&UARTD2); + UARTD2.usart = USART2; + UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmarx = NULL; + UARTD2.dmatx = NULL; +#endif + +#if STM32_UART_USE_USART3 + uartObjectInit(&UARTD3); + UARTD3.usart = USART3; + UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmarx = NULL; + UARTD3.dmatx = NULL; +#endif + +#if STM32_UART_USE_UART4 + uartObjectInit(&UARTD4); + UARTD4.usart = UART4; + UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmarx = NULL; + UARTD4.dmatx = NULL; +#endif + +#if STM32_UART_USE_UART5 + uartObjectInit(&UARTD5); + UARTD5.usart = UART5; + UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmarx = NULL; + UARTD5.dmatx = NULL; +#endif + +#if STM32_UART_USE_USART6 + uartObjectInit(&UARTD6); + UARTD6.usart = USART6; + UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD6.dmarx = NULL; + UARTD6.dmatx = NULL; +#endif + +#if STM32_UART_USE_UART7 + uartObjectInit(&UARTD7); + UARTD7.usart = UART7; + UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD7.dmarx = NULL; + UARTD7.dmatx = NULL; +#endif + +#if STM32_UART_USE_UART8 + uartObjectInit(&UARTD8); + UARTD8.usart = UART8; + UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD8.dmarx = NULL; + UARTD8.dmatx = NULL; +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_start(UARTDriver *uartp) { + + if (uartp->state == UART_STOP) { +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART1(true); + nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART2(true); + nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART3(true); + nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + + osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, + "specified invalid bits in UART4 CR2 register settings"); + osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, + "specified invalid bits in UART4 CR3 register settings"); + + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART4(true); + nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + + osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, + "specified invalid bits in UART5 CR2 register settings"); + osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, + "specified invalid bits in UART5 CR3 register settings"); + + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART5(true); + nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART6(true); + nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_UART7 + if (&UARTD7 == uartp) { + + osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, + "specified invalid bits in UART7 CR2 register settings"); + osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, + "specified invalid bits in UART7 CR3 register settings"); + + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM, + STM32_UART_UART7_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM, + STM32_UART_UART7_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART7(true); + nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_UART8 + if (&UARTD8 == uartp) { + + osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0, + "specified invalid bits in UART8 CR2 register settings"); + osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0, + "specified invalid bits in UART8 CR3 register settings"); + + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM, + STM32_UART_UART8_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM, + STM32_UART_UART8_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART8(true); + nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); + } +#endif + + /* Static DMA setup, the transfer size depends on the USART settings, + it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ + if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) { + uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DR); + dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DR); + uartp->rxbuf = 0; + } + + uartp->rxstate = UART_RX_IDLE; + uartp->txstate = UART_TX_IDLE; + usart_start(uartp); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_stop(UARTDriver *uartp) { + + if (uartp->state == UART_READY) { + usart_stop(uartp); + dmaStreamFreeI(uartp->dmarx); + dmaStreamFreeI(uartp->dmatx); + uartp->dmarx = NULL; + uartp->dmatx = NULL; + +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + nvicDisableVector(STM32_USART1_NUMBER); + rccDisableUSART1(); + return; + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + nvicDisableVector(STM32_USART2_NUMBER); + rccDisableUSART2(); + return; + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + nvicDisableVector(STM32_USART3_NUMBER); + rccDisableUSART3(); + return; + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + nvicDisableVector(STM32_UART4_NUMBER); + rccDisableUART4(); + return; + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + nvicDisableVector(STM32_UART5_NUMBER); + rccDisableUART5(); + return; + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + nvicDisableVector(STM32_USART6_NUMBER); + rccDisableUSART6(); + return; + } +#endif + +#if STM32_UART_USE_UART7 + if (&UARTD7 == uartp) { + nvicDisableVector(STM32_UART7_NUMBER); + rccDisableUART7(); + return; + } +#endif + +#if STM32_UART_USE_UART8 + if (&UARTD8 == uartp) { + nvicDisableVector(STM32_UART8_NUMBER); + rccDisableUART8(); + return; + } +#endif + } +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { + + /* TX DMA channel preparation.*/ + dmaStreamSetMemory0(uartp->dmatx, txbuf); + dmaStreamSetTransactionSize(uartp->dmatx, n); + dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Only enable TC interrupt if there's a callback attached to it or + if called from uartSendFullTimeout(). Also we need to clear TC flag + which could be set before.*/ +#if UART_USE_WAIT == TRUE + if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) { +#else + if (uartp->config->txend2_cb != NULL) { +#endif + uartp->usart->SR = ~USART_SR_TC; + uartp->usart->CR1 |= USART_CR1_TCIE; + } + + /* Starting transfer.*/ + dmaStreamEnable(uartp->dmatx); +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * + * @notapi + */ +size_t uart_lld_stop_send(UARTDriver *uartp) { + + dmaStreamDisable(uartp->dmatx); + + return dmaStreamGetTransactionSize(uartp->dmatx); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { + + /* Stopping previous activity (idle state).*/ + dmaStreamDisable(uartp->dmarx); + + /* RX DMA channel preparation.*/ + dmaStreamSetMemory0(uartp->dmarx, rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, n); + + uint32_t mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE; + + /* DMA half-transfer interrupt & circular mode, if needed */ + if (uartp->config->rxhalf_cb != NULL) + mode |= STM32_DMA_CR_HTIE | STM32_DMA_CR_CIRC; + + dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); + + /* Starting transfer.*/ + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * + * @notapi + */ +size_t uart_lld_stop_receive(UARTDriver *uartp) { + size_t n; + + dmaStreamDisable(uartp->dmarx); + n = dmaStreamGetTransactionSize(uartp->dmarx); + uart_enter_rx_idle_loop(uartp); + + return n; +} + +#endif /* HAL_USE_UART */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h b/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h index 72e492c1fd..c1e17440e8 100644 --- a/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h @@ -1,771 +1,771 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv1/hal_uart_lld.h - * @brief STM32 low level UART driver header. - * - * @addtogroup UART - * @{ - */ - -#ifndef HAL_UART_LLD_H -#define HAL_UART_LLD_H - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief UART driver on USART1 enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART1 FALSE -#endif - -/** - * @brief UART driver on USART2 enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART2 FALSE -#endif - -/** - * @brief UART driver on USART3 enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART3 FALSE -#endif - -/** - * @brief UART driver on UART4 enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART4 FALSE -#endif - -/** - * @brief UART driver on UART5 enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART5 FALSE -#endif - -/** - * @brief UART driver on USART6 enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART6 FALSE -#endif - -/** - * @brief UART driver on UART7 enable switch. - * @details If set to @p TRUE the support for UART7 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART7 FALSE -#endif - -/** - * @brief UART driver on UART8 enable switch. - * @details If set to @p TRUE the support for UART8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART8 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART4_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART5_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART7 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART7_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART8 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART8_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_DMA_PRIORITY 0 -#endif - -/** - * @brief USART2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_DMA_PRIORITY 0 -#endif - -/** - * @brief USART3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_DMA_PRIORITY 0 -#endif - -/** - * @brief UART4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART4_DMA_PRIORITY 0 -#endif - -/** - * @brief UART5 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART5_DMA_PRIORITY 0 -#endif - -/** - * @brief USART6 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART6_DMA_PRIORITY 0 -#endif - -/** - * @brief UART7 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART7_DMA_PRIORITY 0 -#endif - -/** - * @brief UART8 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART8_DMA_PRIORITY 0 -#endif - -/** - * @brief USART DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_UART_USE_UART4 -#if !STM32_HAS_UART4 -#error "UART4 not present in the selected device" -#endif - -#if !defined(STM32F2XX) && !defined(STM32F4XX) && !defined(STM32L151xE) && \ - !defined(STM32L152xE) && !defined(STM32L162xE) -#error "UART4 DMA access not supported in this platform" -#endif -#endif /* STM32_UART_USE_UART4 */ - -#if STM32_UART_USE_UART5 -#if !STM32_HAS_UART5 -#error "UART5 not present in the selected device" -#endif - -#if !defined(STM32F2XX) && !defined(STM32F4XX) && !defined(STM32L151xE) && \ - !defined(STM32L152xE) && !defined(STM32L162xE) -#error "UART5 DMA access not supported in this platform" -#endif -#endif /* STM32_UART_USE_UART5 */ - -#if STM32_UART_USE_USART6 && !STM32_HAS_USART6 -#error "USART6 not present in the selected device" -#endif - -#if STM32_UART_USE_UART7 && !STM32_HAS_UART7 -#error "UART7 not present in the selected device" -#endif - -#if STM32_UART_USE_UART8 && !STM32_HAS_UART8 -#error "UART8 not present in the selected device" -#endif - -#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ - !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ - !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \ - !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8 -#error "UART driver activated but no USART/UART peripheral assigned" -#endif - -#if STM32_UART_USE_USART1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if STM32_UART_USE_UART4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if STM32_UART_USE_UART5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if STM32_UART_USE_USART6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -#if STM32_UART_USE_UART7 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART7" -#endif - -#if STM32_UART_USE_UART8 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART8" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART3" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART4" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART5" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART6" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART7" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART8" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART1_TX_DMA_STREAM)) -#error "USART1 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART2_TX_DMA_STREAM)) -#error "USART2 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART3_TX_DMA_STREAM)) -#error "USART3 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART4_TX_DMA_STREAM)) -#error "UART4 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART5_TX_DMA_STREAM)) -#error "UART5 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART6_TX_DMA_STREAM)) -#error "USART6 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART7_TX_DMA_STREAM)) -#error "UART7 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART8_TX_DMA_STREAM)) -#error "UART8 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_MSK) -#error "invalid DMA stream associated to USART1 RX" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_MSK) -#error "invalid DMA stream associated to USART1 TX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_MSK) -#error "invalid DMA stream associated to USART2 RX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_MSK) -#error "invalid DMA stream associated to USART2 TX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_MSK) -#error "invalid DMA stream associated to USART3 RX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_MSK) -#error "invalid DMA stream associated to USART3 TX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ - STM32_UART4_RX_DMA_MSK) -#error "invalid DMA stream associated to UART4 RX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ - STM32_UART4_TX_DMA_MSK) -#error "invalid DMA stream associated to UART4 TX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ - STM32_UART5_RX_DMA_MSK) -#error "invalid DMA stream associated to UART5 RX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ - STM32_UART5_TX_DMA_MSK) -#error "invalid DMA stream associated to UART5 TX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ - STM32_USART6_RX_DMA_MSK) -#error "invalid DMA stream associated to USART6 RX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ - STM32_USART6_TX_DMA_MSK) -#error "invalid DMA stream associated to USART6 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \ - STM32_UART7_RX_DMA_MSK) -#error "invalid DMA stream associated to UART7 RX" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \ - STM32_UART7_TX_DMA_MSK) -#error "invalid DMA stream associated to UART7 TX" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \ - STM32_UART8_RX_DMA_MSK) -#error "invalid DMA stream associated to UART8 RX" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \ - STM32_UART8_TX_DMA_MSK) -#error "invalid DMA stream associated to UART8 TX" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief UART driver condition flags type. - */ -typedef uint32_t uartflags_t; - -/** - * @brief Structure representing an UART driver. - */ -typedef struct UARTDriver UARTDriver; - -/** - * @brief Generic UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -typedef void (*uartcb_t)(UARTDriver *uartp); - -/** - * @brief Character received UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] c received character - */ -typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); - -/** - * @brief Receive error UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] e receive error mask - */ -typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); - -/** - * @brief Receive Half-transfer UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] full flag set to 1 for the second half, and 0 for the first half - */ -typedef void (*uarthcb_t)(UARTDriver *uartp, uartflags_t full); - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief End of transmission buffer callback. - */ - uartcb_t txend1_cb; - /** - * @brief Physical end of transmission callback. - */ - uartcb_t txend2_cb; - /** - * @brief Receive buffer filled callback. - */ - uartcb_t rxend_cb; - /** - * @brief Character received while out if the @p UART_RECEIVE state. - */ - uartccb_t rxchar_cb; - /** - * @brief Receive error callback. - */ - uartecb_t rxerr_cb; - /* End of the mandatory fields.*/ - /** - * @brief Receiver timeout callback. - * @details Handles idle interrupts depending on configured - * flags in CR registers and supported hardware features. - */ - uartcb_t timeout_cb; - /** - * @brief Bit rate. - */ - uint32_t speed; - /** - * @brief Initialization value for the CR1 register. - */ - uint16_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint16_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint16_t cr3; - /* Additional (optional) handlers. Placed here for the struct compatibility.*/ - /** - * @brief Half-transfer receive buffer callback. - */ - uarthcb_t rxhalf_cb; -} UARTConfig; - -/** - * @brief Structure representing an UART driver. - */ -struct UARTDriver { - /** - * @brief Driver state. - */ - uartstate_t state; - /** - * @brief Transmitter state. - */ - uarttxstate_t txstate; - /** - * @brief Receiver state. - */ - uartrxstate_t rxstate; - /** - * @brief Current configuration data. - */ - const UARTConfig *config; -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) - /** - * @brief Synchronization flag for transmit operations. - */ - bool early; - /** - * @brief Waiting thread on RX. - */ - thread_reference_t threadrx; - /** - * @brief Waiting thread on TX. - */ - thread_reference_t threadtx; -#endif /* UART_USE_WAIT */ -#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the peripheral. - */ - mutex_t mutex; -#endif /* UART_USE_MUTUAL_EXCLUSION */ -#if defined(UART_DRIVER_EXT_FIELDS) - UART_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the USART registers block. - */ - USART_TypeDef *usart; - /** - * @brief Receive DMA mode bit mask. - */ - uint32_t dmarxmode; - /** - * @brief Send DMA mode bit mask. - */ - uint32_t dmatxmode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Default receive buffer while into @p UART_RX_IDLE state. - */ - volatile uint16_t rxbuf; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) -extern UARTDriver UARTD1; -#endif - -#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) -extern UARTDriver UARTD2; -#endif - -#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) -extern UARTDriver UARTD3; -#endif - -#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) -extern UARTDriver UARTD4; -#endif - -#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) -extern UARTDriver UARTD5; -#endif - -#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) -extern UARTDriver UARTD6; -#endif - -#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__) -extern UARTDriver UARTD7; -#endif - -#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__) -extern UARTDriver UARTD8; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void uart_lld_init(void); - void uart_lld_start(UARTDriver *uartp); - void uart_lld_stop(UARTDriver *uartp); - void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); - size_t uart_lld_stop_send(UARTDriver *uartp); - void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); - size_t uart_lld_stop_receive(UARTDriver *uartp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_UART */ - -#endif /* HAL_UART_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv1/hal_uart_lld.h + * @brief STM32 low level UART driver header. + * + * @addtogroup UART + * @{ + */ + +#ifndef HAL_UART_LLD_H +#define HAL_UART_LLD_H + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief UART driver on USART1 enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART1 FALSE +#endif + +/** + * @brief UART driver on USART2 enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART2 FALSE +#endif + +/** + * @brief UART driver on USART3 enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART3 FALSE +#endif + +/** + * @brief UART driver on UART4 enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART4 FALSE +#endif + +/** + * @brief UART driver on UART5 enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART5 FALSE +#endif + +/** + * @brief UART driver on USART6 enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART6 FALSE +#endif + +/** + * @brief UART driver on UART7 enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART7 FALSE +#endif + +/** + * @brief UART driver on UART8 enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART8 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART7_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART8 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART8_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_DMA_PRIORITY 0 +#endif + +/** + * @brief USART2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_DMA_PRIORITY 0 +#endif + +/** + * @brief USART3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_DMA_PRIORITY 0 +#endif + +/** + * @brief UART4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_DMA_PRIORITY 0 +#endif + +/** + * @brief UART5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_DMA_PRIORITY 0 +#endif + +/** + * @brief USART6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_DMA_PRIORITY 0 +#endif + +/** + * @brief UART7 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART7_DMA_PRIORITY 0 +#endif + +/** + * @brief UART8 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART8_DMA_PRIORITY 0 +#endif + +/** + * @brief USART DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_UART_USE_UART4 +#if !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if !defined(STM32F2XX) && !defined(STM32F4XX) && !defined(STM32L151xE) && \ + !defined(STM32L152xE) && !defined(STM32L162xE) +#error "UART4 DMA access not supported in this platform" +#endif +#endif /* STM32_UART_USE_UART4 */ + +#if STM32_UART_USE_UART5 +#if !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if !defined(STM32F2XX) && !defined(STM32F4XX) && !defined(STM32L151xE) && \ + !defined(STM32L152xE) && !defined(STM32L162xE) +#error "UART5 DMA access not supported in this platform" +#endif +#endif /* STM32_UART_USE_UART5 */ + +#if STM32_UART_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if STM32_UART_USE_UART7 && !STM32_HAS_UART7 +#error "UART7 not present in the selected device" +#endif + +#if STM32_UART_USE_UART8 && !STM32_HAS_UART8 +#error "UART8 not present in the selected device" +#endif + +#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ + !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ + !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \ + !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8 +#error "UART driver activated but no USART/UART peripheral assigned" +#endif + +#if STM32_UART_USE_USART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if STM32_UART_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if STM32_UART_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if STM32_UART_USE_USART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if STM32_UART_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +#if STM32_UART_USE_UART8 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART8" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART3" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART4" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART5" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART6" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART7" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART8" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART1_TX_DMA_STREAM)) +#error "USART1 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART2_TX_DMA_STREAM)) +#error "USART2 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART3_TX_DMA_STREAM)) +#error "USART3 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART4_TX_DMA_STREAM)) +#error "UART4 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART5_TX_DMA_STREAM)) +#error "UART5 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART6_TX_DMA_STREAM)) +#error "USART6 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART7_TX_DMA_STREAM)) +#error "UART7 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART8_TX_DMA_STREAM)) +#error "UART8 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_MSK) +#error "invalid DMA stream associated to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_MSK) +#error "invalid DMA stream associated to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_MSK) +#error "invalid DMA stream associated to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_MSK) +#error "invalid DMA stream associated to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_MSK) +#error "invalid DMA stream associated to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_MSK) +#error "invalid DMA stream associated to USART3 TX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_MSK) +#error "invalid DMA stream associated to UART4 RX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_MSK) +#error "invalid DMA stream associated to UART4 TX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_MSK) +#error "invalid DMA stream associated to UART5 RX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_MSK) +#error "invalid DMA stream associated to UART5 TX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_MSK) +#error "invalid DMA stream associated to USART6 RX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_MSK) +#error "invalid DMA stream associated to USART6 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \ + STM32_UART7_RX_DMA_MSK) +#error "invalid DMA stream associated to UART7 RX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \ + STM32_UART7_TX_DMA_MSK) +#error "invalid DMA stream associated to UART7 TX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \ + STM32_UART8_RX_DMA_MSK) +#error "invalid DMA stream associated to UART8 RX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \ + STM32_UART8_TX_DMA_MSK) +#error "invalid DMA stream associated to UART8 TX" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief UART driver condition flags type. + */ +typedef uint32_t uartflags_t; + +/** + * @brief Structure representing an UART driver. + */ +typedef struct UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + +/** + * @brief Receive Half-transfer UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] full flag set to 1 for the second half, and 0 for the first half + */ +typedef void (*uarthcb_t)(UARTDriver *uartp, uartflags_t full); + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief End of transmission buffer callback. + */ + uartcb_t txend1_cb; + /** + * @brief Physical end of transmission callback. + */ + uartcb_t txend2_cb; + /** + * @brief Receive buffer filled callback. + */ + uartcb_t rxend_cb; + /** + * @brief Character received while out if the @p UART_RECEIVE state. + */ + uartccb_t rxchar_cb; + /** + * @brief Receive error callback. + */ + uartecb_t rxerr_cb; + /* End of the mandatory fields.*/ + /** + * @brief Receiver timeout callback. + * @details Handles idle interrupts depending on configured + * flags in CR registers and supported hardware features. + */ + uartcb_t timeout_cb; + /** + * @brief Bit rate. + */ + uint32_t speed; + /** + * @brief Initialization value for the CR1 register. + */ + uint16_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint16_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint16_t cr3; + /* Additional (optional) handlers. Placed here for the struct compatibility.*/ + /** + * @brief Half-transfer receive buffer callback. + */ + uarthcb_t rxhalf_cb; +} UARTConfig; + +/** + * @brief Structure representing an UART driver. + */ +struct UARTDriver { + /** + * @brief Driver state. + */ + uartstate_t state; + /** + * @brief Transmitter state. + */ + uarttxstate_t txstate; + /** + * @brief Receiver state. + */ + uartrxstate_t rxstate; + /** + * @brief Current configuration data. + */ + const UARTConfig *config; +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Synchronization flag for transmit operations. + */ + bool early; + /** + * @brief Waiting thread on RX. + */ + thread_reference_t threadrx; + /** + * @brief Waiting thread on TX. + */ + thread_reference_t threadtx; +#endif /* UART_USE_WAIT */ +#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* UART_USE_MUTUAL_EXCLUSION */ +#if defined(UART_DRIVER_EXT_FIELDS) + UART_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the USART registers block. + */ + USART_TypeDef *usart; + /** + * @brief Receive DMA mode bit mask. + */ + uint32_t dmarxmode; + /** + * @brief Send DMA mode bit mask. + */ + uint32_t dmatxmode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Default receive buffer while into @p UART_RX_IDLE state. + */ + volatile uint16_t rxbuf; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) +extern UARTDriver UARTD1; +#endif + +#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) +extern UARTDriver UARTD2; +#endif + +#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) +extern UARTDriver UARTD3; +#endif + +#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) +extern UARTDriver UARTD4; +#endif + +#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) +extern UARTDriver UARTD5; +#endif + +#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) +extern UARTDriver UARTD6; +#endif + +#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__) +extern UARTDriver UARTD7; +#endif + +#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__) +extern UARTDriver UARTD8; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void uart_lld_init(void); + void uart_lld_start(UARTDriver *uartp); + void uart_lld_stop(UARTDriver *uartp); + void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); + size_t uart_lld_stop_send(UARTDriver *uartp); + void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uart_lld_stop_receive(UARTDriver *uartp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART */ + +#endif /* HAL_UART_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv2/driver.mk b/os/hal/ports/STM32/LLD/USARTv2/driver.mk index 2de63f8e64..6b614601d3 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/driver.mk +++ b/os/hal/ports/STM32/LLD/USARTv2/driver.mk @@ -1,13 +1,13 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c -endif -ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c +endif +ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2 diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c b/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c index 7c89ecf872..27b6a64046 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c @@ -1,913 +1,913 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv2/hal_serial_lld.c - * @brief STM32 low level serial driver code. - * - * @addtogroup SERIAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* For compatibility for those devices without LIN support in the USARTs.*/ -#if !defined(USART_ISR_LBDF) -#define USART_ISR_LBDF 0 -#endif - -#if !defined(USART_CR2_LBDIE) -#define USART_CR2_LBDIE 0 -#endif - -/* Differences in L4+ headers.*/ -#if !defined(USART_CR1_TXEIE) -#define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE -#endif - -#if !defined(USART_CR1_RXNEIE) -#define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE -#endif - -#if !defined(USART_ISR_TXE) -#define USART_ISR_TXE USART_ISR_TXE_TXFNF -#endif - -#if !defined(USART_ISR_RXNE) -#define USART_ISR_RXNE USART_ISR_RXNE_RXFNE -#endif - -/* STM32L0xx/STM32F7xx ST headers difference.*/ -#if !defined(USART_ISR_LBDF) -#define USART_ISR_LBDF USART_ISR_LBD -#endif - -/* Handling differences in frame size bits.*/ -#if !defined(USART_CR1_M_0) -#define USART_CR1_M_0 (1 << 12) -#endif - -#if !defined(USART_CR1_M_1) -#define USART_CR1_M_1 (1 << 28) -#endif - -/* Workarounds for those devices where UARTs are USARTs.*/ -#if defined(USART4) -#define UART4 USART4 -#endif -#if defined(USART5) -#define UART5 USART5 -#endif -#if defined(USART7) -#define UART7 USART7 -#endif -#if defined(USART8) -#define UART8 USART8 -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -SerialDriver SD1; -#endif - -/** @brief USART2 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -SerialDriver SD2; -#endif - -/** @brief USART3 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -SerialDriver SD3; -#endif - -/** @brief UART4 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -SerialDriver SD4; -#endif - -/** @brief UART5 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -SerialDriver SD5; -#endif - -/** @brief USART6 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -SerialDriver SD6; -#endif - -/** @brief UART7 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -SerialDriver SD7; -#endif - -/** @brief UART8 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -SerialDriver SD8; -#endif - -/** @brief LPUART1 serial driver identifier.*/ -#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) -SerialDriver LPSD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** @brief Driver default configuration.*/ -static const SerialConfig default_config = -{ - SERIAL_DEFAULT_BITRATE, - 0, - USART_CR2_STOP1_BITS, - 0 -}; - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -/** @brief Input buffer for SD1.*/ -static uint8_t sd_in_buf1[STM32_SERIAL_USART1_IN_BUF_SIZE]; - -/** @brief Output buffer for SD1.*/ -static uint8_t sd_out_buf1[STM32_SERIAL_USART1_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -/** @brief Input buffer for SD2.*/ -static uint8_t sd_in_buf2[STM32_SERIAL_USART2_IN_BUF_SIZE]; - -/** @brief Output buffer for SD2.*/ -static uint8_t sd_out_buf2[STM32_SERIAL_USART2_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -/** @brief Input buffer for SD3.*/ -static uint8_t sd_in_buf3[STM32_SERIAL_USART3_IN_BUF_SIZE]; - -/** @brief Output buffer for SD3.*/ -static uint8_t sd_out_buf3[STM32_SERIAL_USART3_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -/** @brief Input buffer for SD4.*/ -static uint8_t sd_in_buf4[STM32_SERIAL_UART4_IN_BUF_SIZE]; - -/** @brief Output buffer for SD4.*/ -static uint8_t sd_out_buf4[STM32_SERIAL_UART4_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -/** @brief Input buffer for SD5.*/ -static uint8_t sd_in_buf5[STM32_SERIAL_UART5_IN_BUF_SIZE]; - -/** @brief Output buffer for SD5.*/ -static uint8_t sd_out_buf5[STM32_SERIAL_UART5_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -/** @brief Input buffer for SD6.*/ -static uint8_t sd_in_buf6[STM32_SERIAL_USART6_IN_BUF_SIZE]; - -/** @brief Output buffer for SD6.*/ -static uint8_t sd_out_buf6[STM32_SERIAL_USART6_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -/** @brief Input buffer for SD7.*/ -static uint8_t sd_in_buf7[STM32_SERIAL_UART7_IN_BUF_SIZE]; - -/** @brief Output buffer for SD7.*/ -static uint8_t sd_out_buf7[STM32_SERIAL_UART7_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -/** @brief Input buffer for SD8.*/ -static uint8_t sd_in_buf8[STM32_SERIAL_UART8_IN_BUF_SIZE]; - -/** @brief Output buffer for SD8.*/ -static uint8_t sd_out_buf8[STM32_SERIAL_UART8_OUT_BUF_SIZE]; -#endif - -#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) -/** @brief Input buffer for LPSD1.*/ -static uint8_t sd_in_buflp1[STM32_SERIAL_LPUART1_IN_BUF_SIZE]; - -/** @brief Output buffer for LPSD1.*/ -static uint8_t sd_out_buflp1[STM32_SERIAL_LPUART1_OUT_BUF_SIZE]; -#endif - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration - */ -static void usart_init(SerialDriver *sdp, const SerialConfig *config) { - uint32_t brr; - USART_TypeDef *u = sdp->usart; - - /* Baud rate setting.*/ -#if STM32_SERIAL_USE_LPUART1 - if (sdp == &LPSD1) { - osalDbgAssert((sdp->clock >= config->speed * 3U) && - (sdp->clock <= config->speed * 4096U), - "invalid baud rate vs input clock"); - - brr = (uint32_t)(((uint64_t)sdp->clock * 256) / config->speed); - - osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); - } - else -#endif - { - brr = (uint32_t)(sdp->clock / config->speed); - - /* Correcting BRR value when oversampling by 8 instead of 16. - Fraction is still 4 bits wide, but only lower 3 bits used. - Mantissa is doubled, but Fraction is left the same.*/ - if (config->cr1 & USART_CR1_OVER8) - brr = ((brr & ~7) * 2) | (brr & 7); - - osalDbgAssert(brr < 0x10000, "invalid BRR value"); - } - u->BRR = brr; - - /* Note that some bits are enforced.*/ - u->CR2 = config->cr2 | USART_CR2_LBDIE; - u->CR3 = config->cr3 | USART_CR3_EIE; - u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | - USART_CR1_RXNEIE | USART_CR1_TE | - USART_CR1_RE; - u->ICR = 0xFFFFFFFFU; - - /* Deciding mask to be applied on the data register on receive, this is - required in order to mask out the parity bit.*/ - if ((config->cr1 & USART_CR1_PCE) != 0U) { - switch (config->cr1 & (USART_CR1_M_1 | USART_CR1_M_0)) { - case 0: - sdp->rxmask = 0x7F; - break; - case USART_CR1_M_1: - sdp->rxmask = 0x3F; - break; - default: - sdp->rxmask = 0xFF; - } - } - else { - sdp->rxmask = 0xFF; - } -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] u pointer to an USART I/O block - */ -static void usart_deinit(USART_TypeDef *u) { - - u->CR1 = 0; - u->CR2 = 0; - u->CR3 = 0; -} - -/** - * @brief Error handling routine. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] isr USART ISR register value - */ -static void set_error(SerialDriver *sdp, uint32_t isr) { - eventflags_t sts = 0; - - if (isr & USART_ISR_ORE) - sts |= SD_OVERRUN_ERROR; - if (isr & USART_ISR_PE) - sts |= SD_PARITY_ERROR; - if (isr & USART_ISR_FE) - sts |= SD_FRAMING_ERROR; - if (isr & USART_ISR_NE) - sts |= SD_NOISE_ERROR; - osalSysLockFromISR(); - chnAddFlagsI(sdp, sts); - osalSysUnlockFromISR(); -} - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -static void notify1(io_queue_t *qp) { - - (void)qp; - USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -static void notify2(io_queue_t *qp) { - - (void)qp; - USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -static void notify3(io_queue_t *qp) { - - (void)qp; - USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -static void notify4(io_queue_t *qp) { - - (void)qp; - UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -static void notify5(io_queue_t *qp) { - - (void)qp; - UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -static void notify6(io_queue_t *qp) { - - (void)qp; - USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -static void notify7(io_queue_t *qp) { - - (void)qp; - UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -static void notify8(io_queue_t *qp) { - - (void)qp; - UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) -static void notifylp1(io_queue_t *qp) { - - (void)qp; - LPUART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; -} -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_SUPPRESS_ISR) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_SUPPRESS_ISR) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_SUPPRESS_ISR) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_SUPPRESS_ISR) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_SUPPRESS_ISR) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_SUPPRESS_ISR) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART6 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) -#if !defined(STM32_UART7_SUPPRESS_ISR) -#if !defined(STM32_UART7_HANDLER) -#error "STM32_UART7_HANDLER not defined" -#endif -/** - * @brief UART7 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) -#if !defined(STM32_UART8_SUPPRESS_ISR) -#if !defined(STM32_UART8_HANDLER) -#error "STM32_UART8_HANDLER not defined" -#endif -/** - * @brief UART8 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&SD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) -#if !defined(STM32_LPUART1_SUPPRESS_ISR) -#if !defined(STM32_LPUART1_HANDLER) -#error "STM32_LPUART1_HANDLER not defined" -#endif -/** - * @brief LPUART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_LPUART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - sd_lld_serve_interrupt(&LPSD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level serial driver initialization. - * - * @notapi - */ -void sd_lld_init(void) { - -#if STM32_SERIAL_USE_USART1 - sdObjectInit(&SD1); - iqObjectInit(&SD1.iqueue, sd_in_buf1, sizeof sd_in_buf1, NULL, &SD1); - oqObjectInit(&SD1.oqueue, sd_out_buf1, sizeof sd_out_buf1, notify1, &SD1); - SD1.usart = USART1; - SD1.clock = STM32_USART1CLK; -#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER) - nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_USART2 - sdObjectInit(&SD2); - iqObjectInit(&SD2.iqueue, sd_in_buf2, sizeof sd_in_buf2, NULL, &SD2); - oqObjectInit(&SD2.oqueue, sd_out_buf2, sizeof sd_out_buf2, notify2, &SD2); - SD2.usart = USART2; - SD2.clock = STM32_USART2CLK; -#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER) - nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_USART3 - sdObjectInit(&SD3); - iqObjectInit(&SD3.iqueue, sd_in_buf3, sizeof sd_in_buf3, NULL, &SD3); - oqObjectInit(&SD3.oqueue, sd_out_buf3, sizeof sd_out_buf3, notify3, &SD3); - SD3.usart = USART3; - SD3.clock = STM32_USART3CLK; -#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER) - nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_UART4 - sdObjectInit(&SD4); - iqObjectInit(&SD4.iqueue, sd_in_buf4, sizeof sd_in_buf4, NULL, &SD4); - oqObjectInit(&SD4.oqueue, sd_out_buf4, sizeof sd_out_buf4, notify4, &SD4); - SD4.usart = UART4; - SD4.clock = STM32_UART4CLK; -#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER) - nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_UART5 - sdObjectInit(&SD5); - iqObjectInit(&SD5.iqueue, sd_in_buf5, sizeof sd_in_buf5, NULL, &SD5); - oqObjectInit(&SD5.oqueue, sd_out_buf5, sizeof sd_out_buf5, notify5, &SD5); - SD5.usart = UART5; - SD5.clock = STM32_UART5CLK; -#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER) - nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_USART6 - sdObjectInit(&SD6); - iqObjectInit(&SD6.iqueue, sd_in_buf6, sizeof sd_in_buf6, NULL, &SD6); - oqObjectInit(&SD6.oqueue, sd_out_buf6, sizeof sd_out_buf6, notify6, &SD6); - SD6.usart = USART6; - SD6.clock = STM32_USART6CLK; -#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER) - nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_UART7 - sdObjectInit(&SD7); - iqObjectInit(&SD7.iqueue, sd_in_buf7, sizeof sd_in_buf7, NULL, &SD7); - oqObjectInit(&SD7.oqueue, sd_out_buf7, sizeof sd_out_buf7, notify7, &SD7); - SD7.usart = UART7; - SD7.clock = STM32_UART7CLK; -#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER) - nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_UART8 - sdObjectInit(&SD8); - iqObjectInit(&SD8.iqueue, sd_in_buf8, sizeof sd_in_buf8, NULL, &SD8); - oqObjectInit(&SD8.oqueue, sd_out_buf8, sizeof sd_out_buf8, notify8, &SD8); - SD8.usart = UART8; - SD8.clock = STM32_UART8CLK; -#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER) - nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY); -#endif -#endif - -#if STM32_SERIAL_USE_LPUART1 - sdObjectInit(&LPSD1); - iqObjectInit(&LPSD1.iqueue, sd_in_buflp1, sizeof sd_in_buflp1, NULL, &LPSD1); - oqObjectInit(&LPSD1.oqueue, sd_out_buflp1, sizeof sd_out_buflp1, notifylp1, &LPSD1); - LPSD1.usart = LPUART1; - LPSD1.clock = STM32_LPUART1CLK; -#if !defined(STM32_LPUART1_SUPPRESS_ISR) && defined(STM32_LPUART1_NUMBER) - nvicEnableVector(STM32_LPUART1_NUMBER, STM32_SERIAL_LPUART1_PRIORITY); -#endif -#endif -} - -/** - * @brief Low level serial driver configuration and (re)start. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration. - * If this parameter is set to @p NULL then a default - * configuration is used. - * - * @notapi - */ -void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { - - if (config == NULL) - config = &default_config; - - if (sdp->state == SD_STOP) { -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccEnableUSART1(true); - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccEnableUSART2(true); - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccEnableUSART3(true); - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccEnableUART4(true); - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccEnableUART5(true); - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccEnableUSART6(true); - } -#endif -#if STM32_SERIAL_USE_UART7 - if (&SD7 == sdp) { - rccEnableUART7(true); - } -#endif -#if STM32_SERIAL_USE_UART8 - if (&SD8 == sdp) { - rccEnableUART8(true); - } -#endif -#if STM32_SERIAL_USE_LPUART1 - if (&LPSD1 == sdp) { - rccEnableLPUART1(true); - } -#endif - } - usart_init(sdp, config); -} - -/** - * @brief Low level serial driver stop. - * @details De-initializes the USART, stops the associated clock, resets the - * interrupt vector. - * - * @param[in] sdp pointer to a @p SerialDriver object - * - * @notapi - */ -void sd_lld_stop(SerialDriver *sdp) { - - if (sdp->state == SD_READY) { - /* UART is de-initialized then clocks are disabled.*/ - usart_deinit(sdp->usart); - -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccDisableUSART1(); - return; - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccDisableUSART2(); - return; - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccDisableUSART3(); - return; - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccDisableUART4(); - return; - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccDisableUART5(); - return; - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccDisableUSART6(); - return; - } -#endif -#if STM32_SERIAL_USE_UART7 - if (&SD7 == sdp) { - rccDisableUART7(); - return; - } -#endif -#if STM32_SERIAL_USE_UART8 - if (&SD8 == sdp) { - rccDisableUART8(); - return; - } -#endif -#if STM32_SERIAL_USE_LPUART1 - if (&LPSD1 == sdp) { - rccDisableLPUART1(); - return; - } -#endif - } -} - -/** - * @brief Common IRQ handler. - * - * @param[in] sdp communication channel associated to the USART - */ -void sd_lld_serve_interrupt(SerialDriver *sdp) { - USART_TypeDef *u = sdp->usart; - uint32_t cr1 = u->CR1; - uint32_t isr; - - /* Reading and clearing status.*/ - isr = u->ISR; - u->ICR = isr; - - /* Error condition detection.*/ - if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)) - set_error(sdp, isr); - - /* Special case, LIN break detection.*/ - if (isr & USART_ISR_LBDF) { - osalSysLockFromISR(); - chnAddFlagsI(sdp, SD_BREAK_DETECTED); - osalSysUnlockFromISR(); - } - - /* Data available, note it is a while in order to handle two situations: - 1) Another byte arrived after removing the previous one, this would cause - an extra interrupt to serve. - 2) FIFO mode is enabled on devices that support it, we need to empty - the FIFO.*/ - while (isr & USART_ISR_RXNE) { - osalSysLockFromISR(); - sdIncomingDataI(sdp, (uint8_t)u->RDR & sdp->rxmask); - osalSysUnlockFromISR(); - - isr = u->ISR; - } - - /* Transmission buffer empty, note it is a while in order to handle two - situations: - 1) The data registers has been emptied immediately after writing it, this - would cause an extra interrupt to serve. - 2) FIFO mode is enabled on devices that support it, we need to fill - the FIFO.*/ - if (cr1 & USART_CR1_TXEIE) { - while (isr & USART_ISR_TXE) { - msg_t b; - - osalSysLockFromISR(); - b = oqGetI(&sdp->oqueue); - if (b < MSG_OK) { - chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); - u->CR1 = cr1 & ~USART_CR1_TXEIE; - osalSysUnlockFromISR(); - break; - } - u->TDR = b; - osalSysUnlockFromISR(); - - isr = u->ISR; - } - } - - /* Physical transmission end.*/ - if ((cr1 & USART_CR1_TCIE) && (isr & USART_ISR_TC)) { - osalSysLockFromISR(); - if (oqIsEmptyI(&sdp->oqueue)) { - chnAddFlagsI(sdp, CHN_TRANSMISSION_END); - u->CR1 = cr1 & ~USART_CR1_TCIE; - } - osalSysUnlockFromISR(); - } -} - -#endif /* HAL_USE_SERIAL */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv2/hal_serial_lld.c + * @brief STM32 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* For compatibility for those devices without LIN support in the USARTs.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF 0 +#endif + +#if !defined(USART_CR2_LBDIE) +#define USART_CR2_LBDIE 0 +#endif + +/* Differences in L4+ headers.*/ +#if !defined(USART_CR1_TXEIE) +#define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE +#endif + +#if !defined(USART_CR1_RXNEIE) +#define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE +#endif + +#if !defined(USART_ISR_TXE) +#define USART_ISR_TXE USART_ISR_TXE_TXFNF +#endif + +#if !defined(USART_ISR_RXNE) +#define USART_ISR_RXNE USART_ISR_RXNE_RXFNE +#endif + +/* STM32L0xx/STM32F7xx ST headers difference.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF USART_ISR_LBD +#endif + +/* Handling differences in frame size bits.*/ +#if !defined(USART_CR1_M_0) +#define USART_CR1_M_0 (1 << 12) +#endif + +#if !defined(USART_CR1_M_1) +#define USART_CR1_M_1 (1 << 28) +#endif + +/* Workarounds for those devices where UARTs are USARTs.*/ +#if defined(USART4) +#define UART4 USART4 +#endif +#if defined(USART5) +#define UART5 USART5 +#endif +#if defined(USART7) +#define UART7 USART7 +#endif +#if defined(USART8) +#define UART8 USART8 +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +/** @brief USART2 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +/** @brief USART3 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +SerialDriver SD3; +#endif + +/** @brief UART4 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +/** @brief UART5 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +/** @brief USART6 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + +/** @brief UART7 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +SerialDriver SD7; +#endif + +/** @brief UART8 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +SerialDriver SD8; +#endif + +/** @brief LPUART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +SerialDriver LPSD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** @brief Driver default configuration.*/ +static const SerialConfig default_config = +{ + SERIAL_DEFAULT_BITRATE, + 0, + USART_CR2_STOP1_BITS, + 0 +}; + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +/** @brief Input buffer for SD1.*/ +static uint8_t sd_in_buf1[STM32_SERIAL_USART1_IN_BUF_SIZE]; + +/** @brief Output buffer for SD1.*/ +static uint8_t sd_out_buf1[STM32_SERIAL_USART1_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +/** @brief Input buffer for SD2.*/ +static uint8_t sd_in_buf2[STM32_SERIAL_USART2_IN_BUF_SIZE]; + +/** @brief Output buffer for SD2.*/ +static uint8_t sd_out_buf2[STM32_SERIAL_USART2_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +/** @brief Input buffer for SD3.*/ +static uint8_t sd_in_buf3[STM32_SERIAL_USART3_IN_BUF_SIZE]; + +/** @brief Output buffer for SD3.*/ +static uint8_t sd_out_buf3[STM32_SERIAL_USART3_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +/** @brief Input buffer for SD4.*/ +static uint8_t sd_in_buf4[STM32_SERIAL_UART4_IN_BUF_SIZE]; + +/** @brief Output buffer for SD4.*/ +static uint8_t sd_out_buf4[STM32_SERIAL_UART4_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +/** @brief Input buffer for SD5.*/ +static uint8_t sd_in_buf5[STM32_SERIAL_UART5_IN_BUF_SIZE]; + +/** @brief Output buffer for SD5.*/ +static uint8_t sd_out_buf5[STM32_SERIAL_UART5_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +/** @brief Input buffer for SD6.*/ +static uint8_t sd_in_buf6[STM32_SERIAL_USART6_IN_BUF_SIZE]; + +/** @brief Output buffer for SD6.*/ +static uint8_t sd_out_buf6[STM32_SERIAL_USART6_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +/** @brief Input buffer for SD7.*/ +static uint8_t sd_in_buf7[STM32_SERIAL_UART7_IN_BUF_SIZE]; + +/** @brief Output buffer for SD7.*/ +static uint8_t sd_out_buf7[STM32_SERIAL_UART7_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +/** @brief Input buffer for SD8.*/ +static uint8_t sd_in_buf8[STM32_SERIAL_UART8_IN_BUF_SIZE]; + +/** @brief Output buffer for SD8.*/ +static uint8_t sd_out_buf8[STM32_SERIAL_UART8_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +/** @brief Input buffer for LPSD1.*/ +static uint8_t sd_in_buflp1[STM32_SERIAL_LPUART1_IN_BUF_SIZE]; + +/** @brief Output buffer for LPSD1.*/ +static uint8_t sd_out_buflp1[STM32_SERIAL_LPUART1_OUT_BUF_SIZE]; +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration + */ +static void usart_init(SerialDriver *sdp, const SerialConfig *config) { + uint32_t brr; + USART_TypeDef *u = sdp->usart; + + /* Baud rate setting.*/ +#if STM32_SERIAL_USE_LPUART1 + if (sdp == &LPSD1) { + osalDbgAssert((sdp->clock >= config->speed * 3U) && + (sdp->clock <= config->speed * 4096U), + "invalid baud rate vs input clock"); + + brr = (uint32_t)(((uint64_t)sdp->clock * 256) / config->speed); + + osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); + } + else +#endif + { + brr = (uint32_t)(sdp->clock / config->speed); + + /* Correcting BRR value when oversampling by 8 instead of 16. + Fraction is still 4 bits wide, but only lower 3 bits used. + Mantissa is doubled, but Fraction is left the same.*/ + if (config->cr1 & USART_CR1_OVER8) + brr = ((brr & ~7) * 2) | (brr & 7); + + osalDbgAssert(brr < 0x10000, "invalid BRR value"); + } + u->BRR = brr; + + /* Note that some bits are enforced.*/ + u->CR2 = config->cr2 | USART_CR2_LBDIE; + u->CR3 = config->cr3 | USART_CR3_EIE; + u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | + USART_CR1_RXNEIE | USART_CR1_TE | + USART_CR1_RE; + u->ICR = 0xFFFFFFFFU; + + /* Deciding mask to be applied on the data register on receive, this is + required in order to mask out the parity bit.*/ + if ((config->cr1 & USART_CR1_PCE) != 0U) { + switch (config->cr1 & (USART_CR1_M_1 | USART_CR1_M_0)) { + case 0: + sdp->rxmask = 0x7F; + break; + case USART_CR1_M_1: + sdp->rxmask = 0x3F; + break; + default: + sdp->rxmask = 0xFF; + } + } + else { + sdp->rxmask = 0xFF; + } +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] u pointer to an USART I/O block + */ +static void usart_deinit(USART_TypeDef *u) { + + u->CR1 = 0; + u->CR2 = 0; + u->CR3 = 0; +} + +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] isr USART ISR register value + */ +static void set_error(SerialDriver *sdp, uint32_t isr) { + eventflags_t sts = 0; + + if (isr & USART_ISR_ORE) + sts |= SD_OVERRUN_ERROR; + if (isr & USART_ISR_PE) + sts |= SD_PARITY_ERROR; + if (isr & USART_ISR_FE) + sts |= SD_FRAMING_ERROR; + if (isr & USART_ISR_NE) + sts |= SD_NOISE_ERROR; + osalSysLockFromISR(); + chnAddFlagsI(sdp, sts); + osalSysUnlockFromISR(); +} + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +static void notify1(io_queue_t *qp) { + + (void)qp; + USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +static void notify2(io_queue_t *qp) { + + (void)qp; + USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +static void notify3(io_queue_t *qp) { + + (void)qp; + USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +static void notify4(io_queue_t *qp) { + + (void)qp; + UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +static void notify5(io_queue_t *qp) { + + (void)qp; + UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +static void notify6(io_queue_t *qp) { + + (void)qp; + USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +static void notify7(io_queue_t *qp) { + + (void)qp; + UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +static void notify8(io_queue_t *qp) { + + (void)qp; + UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +static void notifylp1(io_queue_t *qp) { + + (void)qp; + LPUART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_SUPPRESS_ISR) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_SUPPRESS_ISR) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_SUPPRESS_ISR) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_SUPPRESS_ISR) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_SUPPRESS_ISR) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_SUPPRESS_ISR) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +#if !defined(STM32_UART7_SUPPRESS_ISR) +#if !defined(STM32_UART7_HANDLER) +#error "STM32_UART7_HANDLER not defined" +#endif +/** + * @brief UART7 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +#if !defined(STM32_UART8_SUPPRESS_ISR) +#if !defined(STM32_UART8_HANDLER) +#error "STM32_UART8_HANDLER not defined" +#endif +/** + * @brief UART8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +#if !defined(STM32_LPUART1_SUPPRESS_ISR) +#if !defined(STM32_LPUART1_HANDLER) +#error "STM32_LPUART1_HANDLER not defined" +#endif +/** + * @brief LPUART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_LPUART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&LPSD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if STM32_SERIAL_USE_USART1 + sdObjectInit(&SD1); + iqObjectInit(&SD1.iqueue, sd_in_buf1, sizeof sd_in_buf1, NULL, &SD1); + oqObjectInit(&SD1.oqueue, sd_out_buf1, sizeof sd_out_buf1, notify1, &SD1); + SD1.usart = USART1; + SD1.clock = STM32_USART1CLK; +#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER) + nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_USART2 + sdObjectInit(&SD2); + iqObjectInit(&SD2.iqueue, sd_in_buf2, sizeof sd_in_buf2, NULL, &SD2); + oqObjectInit(&SD2.oqueue, sd_out_buf2, sizeof sd_out_buf2, notify2, &SD2); + SD2.usart = USART2; + SD2.clock = STM32_USART2CLK; +#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER) + nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_USART3 + sdObjectInit(&SD3); + iqObjectInit(&SD3.iqueue, sd_in_buf3, sizeof sd_in_buf3, NULL, &SD3); + oqObjectInit(&SD3.oqueue, sd_out_buf3, sizeof sd_out_buf3, notify3, &SD3); + SD3.usart = USART3; + SD3.clock = STM32_USART3CLK; +#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER) + nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART4 + sdObjectInit(&SD4); + iqObjectInit(&SD4.iqueue, sd_in_buf4, sizeof sd_in_buf4, NULL, &SD4); + oqObjectInit(&SD4.oqueue, sd_out_buf4, sizeof sd_out_buf4, notify4, &SD4); + SD4.usart = UART4; + SD4.clock = STM32_UART4CLK; +#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER) + nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART5 + sdObjectInit(&SD5); + iqObjectInit(&SD5.iqueue, sd_in_buf5, sizeof sd_in_buf5, NULL, &SD5); + oqObjectInit(&SD5.oqueue, sd_out_buf5, sizeof sd_out_buf5, notify5, &SD5); + SD5.usart = UART5; + SD5.clock = STM32_UART5CLK; +#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER) + nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_USART6 + sdObjectInit(&SD6); + iqObjectInit(&SD6.iqueue, sd_in_buf6, sizeof sd_in_buf6, NULL, &SD6); + oqObjectInit(&SD6.oqueue, sd_out_buf6, sizeof sd_out_buf6, notify6, &SD6); + SD6.usart = USART6; + SD6.clock = STM32_USART6CLK; +#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER) + nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART7 + sdObjectInit(&SD7); + iqObjectInit(&SD7.iqueue, sd_in_buf7, sizeof sd_in_buf7, NULL, &SD7); + oqObjectInit(&SD7.oqueue, sd_out_buf7, sizeof sd_out_buf7, notify7, &SD7); + SD7.usart = UART7; + SD7.clock = STM32_UART7CLK; +#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER) + nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART8 + sdObjectInit(&SD8); + iqObjectInit(&SD8.iqueue, sd_in_buf8, sizeof sd_in_buf8, NULL, &SD8); + oqObjectInit(&SD8.oqueue, sd_out_buf8, sizeof sd_out_buf8, notify8, &SD8); + SD8.usart = UART8; + SD8.clock = STM32_UART8CLK; +#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER) + nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_LPUART1 + sdObjectInit(&LPSD1); + iqObjectInit(&LPSD1.iqueue, sd_in_buflp1, sizeof sd_in_buflp1, NULL, &LPSD1); + oqObjectInit(&LPSD1.oqueue, sd_out_buflp1, sizeof sd_out_buflp1, notifylp1, &LPSD1); + LPSD1.usart = LPUART1; + LPSD1.clock = STM32_LPUART1CLK; +#if !defined(STM32_LPUART1_SUPPRESS_ISR) && defined(STM32_LPUART1_NUMBER) + nvicEnableVector(STM32_LPUART1_NUMBER, STM32_SERIAL_LPUART1_PRIORITY); +#endif +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) + config = &default_config; + + if (sdp->state == SD_STOP) { +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccEnableUSART1(true); + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccEnableUSART2(true); + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccEnableUSART3(true); + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccEnableUART4(true); + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccEnableUART5(true); + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccEnableUSART6(true); + } +#endif +#if STM32_SERIAL_USE_UART7 + if (&SD7 == sdp) { + rccEnableUART7(true); + } +#endif +#if STM32_SERIAL_USE_UART8 + if (&SD8 == sdp) { + rccEnableUART8(true); + } +#endif +#if STM32_SERIAL_USE_LPUART1 + if (&LPSD1 == sdp) { + rccEnableLPUART1(true); + } +#endif + } + usart_init(sdp, config); +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { + /* UART is de-initialized then clocks are disabled.*/ + usart_deinit(sdp->usart); + +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccDisableUSART1(); + return; + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccDisableUSART2(); + return; + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccDisableUSART3(); + return; + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccDisableUART4(); + return; + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccDisableUART5(); + return; + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccDisableUSART6(); + return; + } +#endif +#if STM32_SERIAL_USE_UART7 + if (&SD7 == sdp) { + rccDisableUART7(); + return; + } +#endif +#if STM32_SERIAL_USE_UART8 + if (&SD8 == sdp) { + rccDisableUART8(); + return; + } +#endif +#if STM32_SERIAL_USE_LPUART1 + if (&LPSD1 == sdp) { + rccDisableLPUART1(); + return; + } +#endif + } +} + +/** + * @brief Common IRQ handler. + * + * @param[in] sdp communication channel associated to the USART + */ +void sd_lld_serve_interrupt(SerialDriver *sdp) { + USART_TypeDef *u = sdp->usart; + uint32_t cr1 = u->CR1; + uint32_t isr; + + /* Reading and clearing status.*/ + isr = u->ISR; + u->ICR = isr; + + /* Error condition detection.*/ + if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)) + set_error(sdp, isr); + + /* Special case, LIN break detection.*/ + if (isr & USART_ISR_LBDF) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, SD_BREAK_DETECTED); + osalSysUnlockFromISR(); + } + + /* Data available, note it is a while in order to handle two situations: + 1) Another byte arrived after removing the previous one, this would cause + an extra interrupt to serve. + 2) FIFO mode is enabled on devices that support it, we need to empty + the FIFO.*/ + while (isr & USART_ISR_RXNE) { + osalSysLockFromISR(); + sdIncomingDataI(sdp, (uint8_t)u->RDR & sdp->rxmask); + osalSysUnlockFromISR(); + + isr = u->ISR; + } + + /* Transmission buffer empty, note it is a while in order to handle two + situations: + 1) The data registers has been emptied immediately after writing it, this + would cause an extra interrupt to serve. + 2) FIFO mode is enabled on devices that support it, we need to fill + the FIFO.*/ + if (cr1 & USART_CR1_TXEIE) { + while (isr & USART_ISR_TXE) { + msg_t b; + + osalSysLockFromISR(); + b = oqGetI(&sdp->oqueue); + if (b < MSG_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + u->CR1 = cr1 & ~USART_CR1_TXEIE; + osalSysUnlockFromISR(); + break; + } + u->TDR = b; + osalSysUnlockFromISR(); + + isr = u->ISR; + } + } + + /* Physical transmission end.*/ + if ((cr1 & USART_CR1_TCIE) && (isr & USART_ISR_TC)) { + osalSysLockFromISR(); + if (oqIsEmptyI(&sdp->oqueue)) { + chnAddFlagsI(sdp, CHN_TRANSMISSION_END); + u->CR1 = cr1 & ~USART_CR1_TCIE; + } + osalSysUnlockFromISR(); + } +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h b/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h index 19ee3291c0..2655d7ca26 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h @@ -1,534 +1,534 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv2/hal_serial_lld.h - * @brief STM32 low level serial driver header. - * - * @addtogroup SERIAL - * @{ - */ - -#ifndef HAL_SERIAL_LLD_H -#define HAL_SERIAL_LLD_H - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Advanced buffering support switch. - * @details This constants enables the advanced buffering support in the - * low level driver, the queue buffer is no more part of the - * @p SerialDriver structure, each driver can have a different - * queue size. - */ -#define SERIAL_ADVANCED_BUFFERING_SUPPORT TRUE - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief USART1 driver enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART1 FALSE -#endif - -/** - * @brief USART2 driver enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART2 FALSE -#endif - -/** - * @brief USART3 driver enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART3 FALSE -#endif - -/** - * @brief UART4 driver enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART4 FALSE -#endif - -/** - * @brief UART5 driver enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART5 FALSE -#endif - -/** - * @brief USART6 driver enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART6 FALSE -#endif - -/** - * @brief UART7 driver enable switch. - * @details If set to @p TRUE the support for UART7 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART7 FALSE -#endif - -/** - * @brief UART8 driver enable switch. - * @details If set to @p TRUE the support for UART8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART8 FALSE -#endif - -/** - * @brief LPUART1 driver enable switch. - * @details If set to @p TRUE the support for LPUART is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_SERIAL_USE_LPUART1) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_LPUART1 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART1_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART2_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART3_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART4_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART5_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART6_PRIORITY 12 -#endif - -/** - * @brief UART7 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART7_PRIORITY 12 -#endif - -/** - * @brief UART8 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART8_PRIORITY 12 -#endif - -/** - * @brief LPUART1 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_LPUART1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_LPUART1_PRIORITY 12 -#endif - -/** - * @brief Input buffer size for USART1. - */ -#if !defined(STM32_SERIAL_USART1_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for USART1. - */ -#if !defined(STM32_SERIAL_USART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for USART2. - */ -#if !defined(STM32_SERIAL_USART2_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART2_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for USART2. - */ -#if !defined(STM32_SERIAL_USART2_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART2_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for USART3. - */ -#if !defined(STM32_SERIAL_USART3_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART3_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for USART3. - */ -#if !defined(STM32_SERIAL_USART3_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART3_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for UART4. - */ -#if !defined(STM32_SERIAL_UART4_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART4_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for UART4. - */ -#if !defined(STM32_SERIAL_UART4_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART4_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for UART5. - */ -#if !defined(STM32_SERIAL_UART5_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART5_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for UART5. - */ -#if !defined(STM32_SERIAL_UART5_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART5_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for USART6. - */ -#if !defined(STM32_SERIAL_USART6_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART6_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for USART6. - */ -#if !defined(STM32_SERIAL_USART6_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART6_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for UART7. - */ -#if !defined(STM32_SERIAL_UART7_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART7_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for UART7. - */ -#if !defined(STM32_SERIAL_UART7_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART7_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for UART8. - */ -#if !defined(STM32_SERIAL_UART8_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART8_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for UART8. - */ -#if !defined(STM32_SERIAL_UART8_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART8_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Input buffer size for LPUART1. - */ -#if !defined(STM32_SERIAL_LPUART1_IN_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_LPUART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif - -/** - * @brief Output buffer size for LPUART1. - */ -#if !defined(STM32_SERIAL_LPUART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) -#define STM32_SERIAL_LPUART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 -#error "UART4 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 -#error "UART5 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 -#error "USART6 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7 -#error "UART7 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8 -#error "UART8 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_LPUART1 && !STM32_HAS_LPUART1 -#error "LPUART1 not present in the selected device" -#endif - -#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ - !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ - !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \ - !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8 && \ - !STM32_SERIAL_USE_LPUART1 -#error "SERIAL driver activated but no USART/UART peripheral assigned" -#endif - -#if !defined(STM32_USART1_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_USART1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if !defined(STM32_USART2_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_USART2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if !defined(STM32_USART3_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_USART3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if !defined(STM32_UART4_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_UART4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if !defined(STM32_UART5_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_UART5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if !defined(STM32_USART6_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_USART6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -#if !defined(STM32_UART7_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_UART7 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY) -#error "Invalid IRQ priority assigned to UART7" -#endif - -#if !defined(STM32_UART8_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_UART8 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY) -#error "Invalid IRQ priority assigned to UART8" -#endif - -#if !defined(STM32_LPUART1_SUPPRESS_ISR) && \ - STM32_SERIAL_USE_LPUART1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_LPUART1_PRIORITY) -#error "Invalid IRQ priority assigned to LPUART1" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 Serial Driver configuration structure. - * @details An instance of this structure must be passed to @p sdStart() - * in order to configure and start a serial driver operations. - * @note This structure content is architecture dependent, each driver - * implementation defines its own version and the custom static - * initializers. - */ -typedef struct { - /** - * @brief Bit rate. - */ - uint32_t speed; - /* End of the mandatory fields.*/ - /** - * @brief Initialization value for the CR1 register. - */ - uint32_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint32_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint32_t cr3; -} SerialConfig; - -/** - * @brief @p SerialDriver specific data. - */ -#define _serial_driver_data \ - _base_asynchronous_channel_data \ - /* Driver state.*/ \ - sdstate_t state; \ - /* Input queue.*/ \ - input_queue_t iqueue; \ - /* Output queue.*/ \ - output_queue_t oqueue; \ - /* End of the mandatory fields.*/ \ - /* Pointer to the USART registers block.*/ \ - USART_TypeDef *usart; \ - /* Clock frequency for the associated USART/UART.*/ \ - uint32_t clock; \ - /* Mask to be applied on received frames.*/ \ - uint8_t rxmask; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/* - * Extra USARTs definitions here (missing from the ST header file). - */ -#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ -#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ -#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ -#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) -extern SerialDriver SD1; -#endif -#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) -extern SerialDriver SD2; -#endif -#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) -extern SerialDriver SD3; -#endif -#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) -extern SerialDriver SD4; -#endif -#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) -extern SerialDriver SD5; -#endif -#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) -extern SerialDriver SD6; -#endif -#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__) -extern SerialDriver SD7; -#endif -#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__) -extern SerialDriver SD8; -#endif -#if STM32_SERIAL_USE_LPUART1 && !defined(__DOXYGEN__) -extern SerialDriver LPSD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sd_lld_init(void); - void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); - void sd_lld_stop(SerialDriver *sdp); - void sd_lld_serve_interrupt(SerialDriver *sdp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SERIAL */ - -#endif /* HAL_SERIAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv2/hal_serial_lld.h + * @brief STM32 low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef HAL_SERIAL_LLD_H +#define HAL_SERIAL_LLD_H + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Advanced buffering support switch. + * @details This constants enables the advanced buffering support in the + * low level driver, the queue buffer is no more part of the + * @p SerialDriver structure, each driver can have a different + * queue size. + */ +#define SERIAL_ADVANCED_BUFFERING_SUPPORT TRUE + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART1 FALSE +#endif + +/** + * @brief USART2 driver enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART2 FALSE +#endif + +/** + * @brief USART3 driver enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART3 FALSE +#endif + +/** + * @brief UART4 driver enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART4 FALSE +#endif + +/** + * @brief UART5 driver enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief USART6 driver enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART6 FALSE +#endif + +/** + * @brief UART7 driver enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART7 FALSE +#endif + +/** + * @brief UART8 driver enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART8 FALSE +#endif + +/** + * @brief LPUART1 driver enable switch. + * @details If set to @p TRUE the support for LPUART is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_LPUART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_LPUART1 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_PRIORITY 12 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_PRIORITY 12 +#endif + +/** + * @brief UART8 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_PRIORITY 12 +#endif + +/** + * @brief LPUART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_LPUART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_LPUART1_PRIORITY 12 +#endif + +/** + * @brief Input buffer size for USART1. + */ +#if !defined(STM32_SERIAL_USART1_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART1. + */ +#if !defined(STM32_SERIAL_USART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for USART2. + */ +#if !defined(STM32_SERIAL_USART2_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART2. + */ +#if !defined(STM32_SERIAL_USART2_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for USART3. + */ +#if !defined(STM32_SERIAL_USART3_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART3. + */ +#if !defined(STM32_SERIAL_USART3_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART4. + */ +#if !defined(STM32_SERIAL_UART4_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART4. + */ +#if !defined(STM32_SERIAL_UART4_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART5. + */ +#if !defined(STM32_SERIAL_UART5_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART5. + */ +#if !defined(STM32_SERIAL_UART5_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for USART6. + */ +#if !defined(STM32_SERIAL_USART6_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART6. + */ +#if !defined(STM32_SERIAL_USART6_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART7. + */ +#if !defined(STM32_SERIAL_UART7_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART7. + */ +#if !defined(STM32_SERIAL_UART7_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART8. + */ +#if !defined(STM32_SERIAL_UART8_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART8. + */ +#if !defined(STM32_SERIAL_UART8_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for LPUART1. + */ +#if !defined(STM32_SERIAL_LPUART1_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_LPUART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for LPUART1. + */ +#if !defined(STM32_SERIAL_LPUART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_LPUART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7 +#error "UART7 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8 +#error "UART8 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_LPUART1 && !STM32_HAS_LPUART1 +#error "LPUART1 not present in the selected device" +#endif + +#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ + !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ + !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \ + !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8 && \ + !STM32_SERIAL_USE_LPUART1 +#error "SERIAL driver activated but no USART/UART peripheral assigned" +#endif + +#if !defined(STM32_USART1_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if !defined(STM32_USART2_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if !defined(STM32_USART3_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if !defined(STM32_UART4_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if !defined(STM32_UART5_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if !defined(STM32_USART6_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if !defined(STM32_UART7_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +#if !defined(STM32_UART8_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART8 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY) +#error "Invalid IRQ priority assigned to UART8" +#endif + +#if !defined(STM32_LPUART1_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_LPUART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_LPUART1_PRIORITY) +#error "Invalid IRQ priority assigned to LPUART1" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t speed; + /* End of the mandatory fields.*/ + /** + * @brief Initialization value for the CR1 register. + */ + uint32_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint32_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint32_t cr3; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the USART registers block.*/ \ + USART_TypeDef *usart; \ + /* Clock frequency for the associated USART/UART.*/ \ + uint32_t clock; \ + /* Mask to be applied on received frames.*/ \ + uint8_t rxmask; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * Extra USARTs definitions here (missing from the ST header file). + */ +#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ +#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ +#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ +#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif +#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif +#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif +#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif +#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif +#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__) +extern SerialDriver SD7; +#endif +#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__) +extern SerialDriver SD8; +#endif +#if STM32_SERIAL_USE_LPUART1 && !defined(__DOXYGEN__) +extern SerialDriver LPSD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); + void sd_lld_serve_interrupt(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* HAL_SERIAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c b/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c index 37877168aa..d28bc0e129 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c @@ -1,1075 +1,1075 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv2/hal_uart_lld.c - * @brief STM32 low level UART driver code. - * - * @addtogroup UART - * @{ - */ - -#include "hal.h" - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/* For compatibility for those devices without LIN support in the USARTs.*/ -#if !defined(USART_ISR_LBDF) -#define USART_ISR_LBDF 0 -#endif - -#if !defined(USART_CR2_LBDIE) -#define USART_CR2_LBDIE 0 -#endif - -/* STM32L0xx/STM32F7xx ST headers difference.*/ -#if !defined(USART_ISR_LBDF) -#define USART_ISR_LBDF USART_ISR_LBD -#endif - -/* STM32L0xx/STM32F7xx ST headers difference.*/ -#if !defined(USART_ISR_LBDF) -#define USART_ISR_LBDF USART_ISR_LBD -#endif - -#define USART1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_CHN) - -#define USART1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_CHN) - -#define USART2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_CHN) - -#define USART2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_CHN) - -#define USART3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_CHN) - -#define USART3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_CHN) - -#define UART4_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ - STM32_UART4_RX_DMA_CHN) - -#define UART4_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ - STM32_UART4_TX_DMA_CHN) - -#define UART5_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ - STM32_UART5_RX_DMA_CHN) - -#define UART5_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ - STM32_UART5_TX_DMA_CHN) - -#define USART6_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ - STM32_USART6_RX_DMA_CHN) - -#define USART6_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ - STM32_USART6_TX_DMA_CHN) - -#define UART7_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \ - STM32_UART7_RX_DMA_CHN) - -#define UART7_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \ - STM32_UART7_TX_DMA_CHN) - -#define UART8_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \ - STM32_UART8_RX_DMA_CHN) - -#define UART8_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \ - STM32_UART8_TX_DMA_CHN) - -/* Workarounds for those devices where UARTs are USARTs.*/ -#if defined(USART4) -#define UART4 USART4 -#endif -#if defined(USART5) -#define UART5 USART5 -#endif -#if defined(USART7) -#define UART7 USART7 -#endif -#if defined(USART8) -#define UART8 USART8 -#endif - -/* Workaround for more differences in headers.*/ -#if !defined(USART_CR1_M0) -#define USART_CR1_M0 USART_CR1_M -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 UART driver identifier.*/ -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -UARTDriver UARTD1; -#endif - -/** @brief USART2 UART driver identifier.*/ -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -UARTDriver UARTD2; -#endif - -/** @brief USART3 UART driver identifier.*/ -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -UARTDriver UARTD3; -#endif - -/** @brief UART4 UART driver identifier.*/ -#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) -UARTDriver UARTD4; -#endif - -/** @brief UART5 UART driver identifier.*/ -#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) -UARTDriver UARTD5; -#endif - -/** @brief USART6 UART driver identifier.*/ -#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) -UARTDriver UARTD6; -#endif - -/** @brief UART7 UART driver identifier.*/ -#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) -UARTDriver UARTD7; -#endif - -/** @brief UART8 UART driver identifier.*/ -#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) -UARTDriver UARTD8; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Status bits translation. - * - * @param[in] isr USART SR register value - * - * @return The error flags. - */ -static uartflags_t translate_errors(uint32_t isr) { - uartflags_t sts = 0; - - if (isr & USART_ISR_ORE) - sts |= UART_OVERRUN_ERROR; - if (isr & USART_ISR_PE) - sts |= UART_PARITY_ERROR; - if (isr & USART_ISR_FE) - sts |= UART_FRAMING_ERROR; - if (isr & USART_ISR_NE) - sts |= UART_NOISE_ERROR; - if (isr & USART_ISR_LBDF) - sts |= UART_BREAK_DETECTED; - return sts; -} - -/** - * @brief Puts the receiver in the UART_RX_IDLE state. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void uart_enter_rx_idle_loop(UARTDriver *uartp) { - uint32_t mode; - - /* RX DMA channel preparation, if the char callback is defined then the - TCIE interrupt is enabled too.*/ - if (uartp->config->rxchar_cb == NULL) - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; - else - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; - dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, 1); - dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_stop(UARTDriver *uartp) { - - /* Stops RX and TX DMA channels.*/ - dmaStreamDisable(uartp->dmarx); - dmaStreamDisable(uartp->dmatx); - - /* Stops USART operations.*/ - uartp->usart->CR1 = 0; - uartp->usart->CR2 = 0; - uartp->usart->CR3 = 0; -} - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_start(UARTDriver *uartp) { - uint32_t fck; - uint32_t cr1; - const uint32_t tmo = uartp->config->timeout; - USART_TypeDef *u = uartp->usart; - - /* Defensive programming, starting from a clean state.*/ - usart_stop(uartp); - - /* Baud rate setting.*/ - fck = (uint32_t)(uartp->clock / uartp->config->speed); - - /* Correcting USARTDIV when oversampling by 8 instead of 16. - Fraction is still 4 bits wide, but only lower 3 bits used. - Mantissa is doubled, but Fraction is left the same.*/ - if (uartp->config->cr1 & USART_CR1_OVER8) - fck = ((fck & ~7) * 2) | (fck & 7); - u->BRR = fck; - - /* Resetting eventual pending status flags.*/ - u->ICR = 0xFFFFFFFFU; - - /* Note that some bits are enforced because required for correct driver - operations.*/ - u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; - u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | - USART_CR3_EIE; - - /* Mustn't ever set TCIE here - if done, it causes an immediate - interrupt.*/ - cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; - u->CR1 = uartp->config->cr1 | cr1; - - /* Set receive timeout and checks if it is really applied.*/ - if (tmo > 0) { - osalDbgAssert(tmo <= USART_RTOR_RTO, "Timeout overflow"); - u->RTOR = tmo; - osalDbgAssert(tmo == u->RTOR, "Timeout feature unsupported in this UART"); - } - - /* Starting the receiver idle loop.*/ - uart_enter_rx_idle_loop(uartp); -} - -/** - * @brief RX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - if (uartp->rxstate == UART_RX_IDLE) { - /* Receiver in idle state, a callback is generated, if enabled, for each - received character and then the driver stays in the same state.*/ - _uart_rx_idle_code(uartp); - } - else { - /* Receiver in active state, a callback is generated, if enabled, after - a completed transfer.*/ - dmaStreamDisable(uartp->dmarx); - _uart_rx_complete_isr_code(uartp); - } -} - -/** - * @brief TX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(uartp->dmatx); - - /* A callback is generated, if enabled, after a completed transfer.*/ - _uart_tx1_isr_code(uartp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_SUPPRESS_ISR) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_SUPPRESS_ISR) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_SUPPRESS_ISR) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_SUPPRESS_ISR) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_SUPPRESS_ISR) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_SUPPRESS_ISR) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART6 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) -#if !defined(STM32_UART7_SUPPRESS_ISR) -#if !defined(STM32_UART7_HANDLER) -#error "STM32_UART7_HANDLER not defined" -#endif -/** - * @brief UART7 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) -#if !defined(STM32_UART8_SUPPRESS_ISR) -#if !defined(STM32_UART8_HANDLER) -#error "STM32_UART8_HANDLER not defined" -#endif -/** - * @brief UART8 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - uart_lld_serve_interrupt(&UARTD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level UART driver initialization. - * - * @notapi - */ -void uart_lld_init(void) { - -#if STM32_UART_USE_USART1 - uartObjectInit(&UARTD1); - UARTD1.usart = USART1; - UARTD1.clock = STM32_USART1CLK; - UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD1.dmarx = NULL; - UARTD1.dmatx = NULL; -#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER) - nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_USART2 - uartObjectInit(&UARTD2); - UARTD2.usart = USART2; - UARTD2.clock = STM32_USART2CLK; - UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD2.dmarx = NULL; - UARTD2.dmatx = NULL; -#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER) - nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_USART3 - uartObjectInit(&UARTD3); - UARTD3.usart = USART3; - UARTD3.clock = STM32_USART3CLK; - UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD3.dmarx = NULL; - UARTD3.dmatx = NULL; -#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER) - nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_UART4 - uartObjectInit(&UARTD4); - UARTD4.usart = UART4; - UARTD4.clock = STM32_UART4CLK; - UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD4.dmarx = NULL; - UARTD4.dmatx = NULL; -#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER) - nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_UART5 - uartObjectInit(&UARTD5); - UARTD5.usart = UART5; - UARTD5.clock = STM32_UART5CLK; - UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD5.dmarx = NULL; - UARTD5.dmatx = NULL; -#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER) - nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_USART6 - uartObjectInit(&UARTD6); - UARTD6.usart = USART6; - UARTD6.clock = STM32_USART6CLK; - UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD6.dmarx = NULL; - UARTD6.dmatx = NULL; -#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER) - nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_UART7 - uartObjectInit(&UARTD7); - UARTD7.usart = UART7; - UARTD7.clock = STM32_UART7CLK; - UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD7.dmarx = NULL; - UARTD7.dmatx = NULL; -#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER) - nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY); -#endif -#endif - -#if STM32_UART_USE_UART8 - uartObjectInit(&UARTD8); - UARTD8.usart = UART8; - UARTD8.clock = STM32_UART8CLK; - UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD8.dmarx = NULL; - UARTD8.dmatx = NULL; -#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER) - nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY); -#endif -#endif -} - -/** - * @brief Configures and activates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_start(UARTDriver *uartp) { - - if (uartp->state == UART_STOP) { -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART1(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART1_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART1_TX); -#endif - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART2(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART2_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART2_TX); -#endif - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART3(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART3_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART3_TX); -#endif - } -#endif - -#if STM32_UART_USE_UART4 - if (&UARTD4 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM, - STM32_UART_UART4_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM, - STM32_UART_UART4_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART4(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART4_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART4_TX); -#endif - } -#endif - -#if STM32_UART_USE_UART5 - if (&UARTD5 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM, - STM32_UART_UART5_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM, - STM32_UART_UART5_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART5(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART5_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART5_TX); -#endif - } -#endif - -#if STM32_UART_USE_USART6 - if (&UARTD6 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM, - STM32_UART_USART6_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM, - STM32_UART_USART6_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUSART6(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART6_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART6_TX); -#endif - } -#endif - -#if STM32_UART_USE_UART7 - if (&UARTD7 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM, - STM32_UART_UART7_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM, - STM32_UART_UART7_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART7(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART7_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART7_TX); -#endif - } -#endif - -#if STM32_UART_USE_UART8 - if (&UARTD8 == uartp) { - uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM, - STM32_UART_UART8_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); - uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM, - STM32_UART_UART8_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); - - rccEnableUART8(true); - uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); - uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); -#if STM32_DMA_SUPPORTS_DMAMUX - dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART8_RX); - dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART8_TX); -#endif - } -#endif - - /* Static DMA setup, the transfer size depends on the USART settings, - it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ - if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M0) { - uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->RDR); - dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->TDR); - uartp->rxbuf = 0; - } - - uartp->rxstate = UART_RX_IDLE; - uartp->txstate = UART_TX_IDLE; - usart_start(uartp); -} - -/** - * @brief Deactivates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_stop(UARTDriver *uartp) { - - if (uartp->state == UART_READY) { - usart_stop(uartp); - dmaStreamFreeI(uartp->dmarx); - dmaStreamFreeI(uartp->dmatx); - uartp->dmarx = NULL; - uartp->dmatx = NULL; - -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - rccDisableUSART1(); - return; - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - rccDisableUSART2(); - return; - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - rccDisableUSART3(); - return; - } -#endif - -#if STM32_UART_USE_UART4 - if (&UARTD4 == uartp) { - rccDisableUART4(); - return; - } -#endif - -#if STM32_UART_USE_UART5 - if (&UARTD5 == uartp) { - rccDisableUART5(); - return; - } -#endif - -#if STM32_UART_USE_USART6 - if (&UARTD6 == uartp) { - rccDisableUSART6(); - return; - } -#endif - -#if STM32_UART_USE_UART7 - if (&UARTD7 == uartp) { - rccDisableUART7(); - return; - } -#endif - -#if STM32_UART_USE_UART8 - if (&UARTD8 == uartp) { - rccDisableUART8(); - return; - } -#endif - } -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { - - /* TX DMA channel preparation.*/ - dmaStreamSetMemory0(uartp->dmatx, txbuf); - dmaStreamSetTransactionSize(uartp->dmatx, n); - dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - - /* Only enable TC interrupt if there's a callback attached to it or - if called from uartSendFullTimeout(). Also we need to clear TC flag - which could be set before.*/ -#if UART_USE_WAIT == TRUE - if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) { -#else - if (uartp->config->txend2_cb != NULL) { -#endif - uartp->usart->ICR = USART_ICR_TCCF; - uartp->usart->CR1 |= USART_CR1_TCIE; - } - - /* Starting transfer.*/ - dmaStreamEnable(uartp->dmatx); -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * - * @notapi - */ -size_t uart_lld_stop_send(UARTDriver *uartp) { - - dmaStreamDisable(uartp->dmatx); - - return dmaStreamGetTransactionSize(uartp->dmatx); -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { - - /* Stopping previous activity (idle state).*/ - dmaStreamDisable(uartp->dmarx); - - /* RX DMA channel preparation.*/ - dmaStreamSetMemory0(uartp->dmarx, rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, n); - dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - - /* Starting transfer.*/ - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * - * @notapi - */ -size_t uart_lld_stop_receive(UARTDriver *uartp) { - size_t n; - - dmaStreamDisable(uartp->dmarx); - n = dmaStreamGetTransactionSize(uartp->dmarx); - uart_enter_rx_idle_loop(uartp); - - return n; -} - -/** - * @brief USART common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -void uart_lld_serve_interrupt(UARTDriver *uartp) { - uint32_t isr; - USART_TypeDef *u = uartp->usart; - uint32_t cr1 = u->CR1; - - /* Reading and clearing status.*/ - isr = u->ISR; - u->ICR = isr; - - if (isr & (USART_ISR_LBDF | USART_ISR_ORE | USART_ISR_NE | - USART_ISR_FE | USART_ISR_PE)) { - _uart_rx_error_isr_code(uartp, translate_errors(isr)); - } - - if ((isr & USART_ISR_TC) && (cr1 & USART_CR1_TCIE)) { - /* TC interrupt disabled.*/ - u->CR1 = cr1 & ~USART_CR1_TCIE; - - /* End of transmission, a callback is generated.*/ - _uart_tx2_isr_code(uartp); - } - - /* Timeout interrupt sources are only checked if enabled in CR1.*/ - if (((cr1 & USART_CR1_IDLEIE) && (isr & USART_ISR_IDLE)) || - ((cr1 & USART_CR1_RTOIE) && (isr & USART_ISR_RTOF))) { - _uart_timeout_isr_code(uartp); - } -} - -#endif /* HAL_USE_UART */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv2/hal_uart_lld.c + * @brief STM32 low level UART driver code. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* For compatibility for those devices without LIN support in the USARTs.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF 0 +#endif + +#if !defined(USART_CR2_LBDIE) +#define USART_CR2_LBDIE 0 +#endif + +/* STM32L0xx/STM32F7xx ST headers difference.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF USART_ISR_LBD +#endif + +/* STM32L0xx/STM32F7xx ST headers difference.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF USART_ISR_LBD +#endif + +#define USART1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_CHN) + +#define USART1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_CHN) + +#define USART2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_CHN) + +#define USART2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_CHN) + +#define USART3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_CHN) + +#define USART3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_CHN) + +#define UART4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_CHN) + +#define UART4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_CHN) + +#define UART5_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_CHN) + +#define UART5_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_CHN) + +#define USART6_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_CHN) + +#define USART6_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_CHN) + +#define UART7_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \ + STM32_UART7_RX_DMA_CHN) + +#define UART7_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \ + STM32_UART7_TX_DMA_CHN) + +#define UART8_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \ + STM32_UART8_RX_DMA_CHN) + +#define UART8_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \ + STM32_UART8_TX_DMA_CHN) + +/* Workarounds for those devices where UARTs are USARTs.*/ +#if defined(USART4) +#define UART4 USART4 +#endif +#if defined(USART5) +#define UART5 USART5 +#endif +#if defined(USART7) +#define UART7 USART7 +#endif +#if defined(USART8) +#define UART8 USART8 +#endif + +/* Workaround for more differences in headers.*/ +#if !defined(USART_CR1_M0) +#define USART_CR1_M0 USART_CR1_M +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 UART driver identifier.*/ +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +UARTDriver UARTD1; +#endif + +/** @brief USART2 UART driver identifier.*/ +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +UARTDriver UARTD2; +#endif + +/** @brief USART3 UART driver identifier.*/ +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +UARTDriver UARTD3; +#endif + +/** @brief UART4 UART driver identifier.*/ +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +UARTDriver UARTD4; +#endif + +/** @brief UART5 UART driver identifier.*/ +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +UARTDriver UARTD5; +#endif + +/** @brief USART6 UART driver identifier.*/ +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +UARTDriver UARTD6; +#endif + +/** @brief UART7 UART driver identifier.*/ +#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) +UARTDriver UARTD7; +#endif + +/** @brief UART8 UART driver identifier.*/ +#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) +UARTDriver UARTD8; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Status bits translation. + * + * @param[in] isr USART SR register value + * + * @return The error flags. + */ +static uartflags_t translate_errors(uint32_t isr) { + uartflags_t sts = 0; + + if (isr & USART_ISR_ORE) + sts |= UART_OVERRUN_ERROR; + if (isr & USART_ISR_PE) + sts |= UART_PARITY_ERROR; + if (isr & USART_ISR_FE) + sts |= UART_FRAMING_ERROR; + if (isr & USART_ISR_NE) + sts |= UART_NOISE_ERROR; + if (isr & USART_ISR_LBDF) + sts |= UART_BREAK_DETECTED; + return sts; +} + +/** + * @brief Puts the receiver in the UART_RX_IDLE state. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void uart_enter_rx_idle_loop(UARTDriver *uartp) { + uint32_t mode; + + /* RX DMA channel preparation, if the char callback is defined then the + TCIE interrupt is enabled too.*/ + if (uartp->config->rxchar_cb == NULL) + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; + else + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; + dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, 1); + dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_stop(UARTDriver *uartp) { + + /* Stops RX and TX DMA channels.*/ + dmaStreamDisable(uartp->dmarx); + dmaStreamDisable(uartp->dmatx); + + /* Stops USART operations.*/ + uartp->usart->CR1 = 0; + uartp->usart->CR2 = 0; + uartp->usart->CR3 = 0; +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_start(UARTDriver *uartp) { + uint32_t fck; + uint32_t cr1; + const uint32_t tmo = uartp->config->timeout; + USART_TypeDef *u = uartp->usart; + + /* Defensive programming, starting from a clean state.*/ + usart_stop(uartp); + + /* Baud rate setting.*/ + fck = (uint32_t)(uartp->clock / uartp->config->speed); + + /* Correcting USARTDIV when oversampling by 8 instead of 16. + Fraction is still 4 bits wide, but only lower 3 bits used. + Mantissa is doubled, but Fraction is left the same.*/ + if (uartp->config->cr1 & USART_CR1_OVER8) + fck = ((fck & ~7) * 2) | (fck & 7); + u->BRR = fck; + + /* Resetting eventual pending status flags.*/ + u->ICR = 0xFFFFFFFFU; + + /* Note that some bits are enforced because required for correct driver + operations.*/ + u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; + u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | + USART_CR3_EIE; + + /* Mustn't ever set TCIE here - if done, it causes an immediate + interrupt.*/ + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; + u->CR1 = uartp->config->cr1 | cr1; + + /* Set receive timeout and checks if it is really applied.*/ + if (tmo > 0) { + osalDbgAssert(tmo <= USART_RTOR_RTO, "Timeout overflow"); + u->RTOR = tmo; + osalDbgAssert(tmo == u->RTOR, "Timeout feature unsupported in this UART"); + } + + /* Starting the receiver idle loop.*/ + uart_enter_rx_idle_loop(uartp); +} + +/** + * @brief RX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + if (uartp->rxstate == UART_RX_IDLE) { + /* Receiver in idle state, a callback is generated, if enabled, for each + received character and then the driver stays in the same state.*/ + _uart_rx_idle_code(uartp); + } + else { + /* Receiver in active state, a callback is generated, if enabled, after + a completed transfer.*/ + dmaStreamDisable(uartp->dmarx); + _uart_rx_complete_isr_code(uartp); + } +} + +/** + * @brief TX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(uartp->dmatx); + + /* A callback is generated, if enabled, after a completed transfer.*/ + _uart_tx1_isr_code(uartp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_SUPPRESS_ISR) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_SUPPRESS_ISR) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_SUPPRESS_ISR) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_SUPPRESS_ISR) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_SUPPRESS_ISR) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_SUPPRESS_ISR) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) +#if !defined(STM32_UART7_SUPPRESS_ISR) +#if !defined(STM32_UART7_HANDLER) +#error "STM32_UART7_HANDLER not defined" +#endif +/** + * @brief UART7 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) +#if !defined(STM32_UART8_SUPPRESS_ISR) +#if !defined(STM32_UART8_HANDLER) +#error "STM32_UART8_HANDLER not defined" +#endif +/** + * @brief UART8 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level UART driver initialization. + * + * @notapi + */ +void uart_lld_init(void) { + +#if STM32_UART_USE_USART1 + uartObjectInit(&UARTD1); + UARTD1.usart = USART1; + UARTD1.clock = STM32_USART1CLK; + UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmarx = NULL; + UARTD1.dmatx = NULL; +#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER) + nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_USART2 + uartObjectInit(&UARTD2); + UARTD2.usart = USART2; + UARTD2.clock = STM32_USART2CLK; + UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmarx = NULL; + UARTD2.dmatx = NULL; +#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER) + nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_USART3 + uartObjectInit(&UARTD3); + UARTD3.usart = USART3; + UARTD3.clock = STM32_USART3CLK; + UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmarx = NULL; + UARTD3.dmatx = NULL; +#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER) + nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART4 + uartObjectInit(&UARTD4); + UARTD4.usart = UART4; + UARTD4.clock = STM32_UART4CLK; + UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmarx = NULL; + UARTD4.dmatx = NULL; +#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER) + nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART5 + uartObjectInit(&UARTD5); + UARTD5.usart = UART5; + UARTD5.clock = STM32_UART5CLK; + UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmarx = NULL; + UARTD5.dmatx = NULL; +#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER) + nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_USART6 + uartObjectInit(&UARTD6); + UARTD6.usart = USART6; + UARTD6.clock = STM32_USART6CLK; + UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD6.dmarx = NULL; + UARTD6.dmatx = NULL; +#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER) + nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART7 + uartObjectInit(&UARTD7); + UARTD7.usart = UART7; + UARTD7.clock = STM32_UART7CLK; + UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD7.dmarx = NULL; + UARTD7.dmatx = NULL; +#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER) + nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART8 + uartObjectInit(&UARTD8); + UARTD8.usart = UART8; + UARTD8.clock = STM32_UART8CLK; + UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD8.dmarx = NULL; + UARTD8.dmatx = NULL; +#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER) + nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY); +#endif +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_start(UARTDriver *uartp) { + + if (uartp->state == UART_STOP) { +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART1(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART1_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART1_TX); +#endif + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART2(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART2_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART2_TX); +#endif + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART3(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART3_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART3_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART4(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART4_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART4_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART5(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART5_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART5_TX); +#endif + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART6(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART6_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART6_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART7 + if (&UARTD7 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM, + STM32_UART_UART7_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM, + STM32_UART_UART7_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART7(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART7_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART7_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART8 + if (&UARTD8 == uartp) { + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM, + STM32_UART_UART8_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM, + STM32_UART_UART8_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART8(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART8_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART8_TX); +#endif + } +#endif + + /* Static DMA setup, the transfer size depends on the USART settings, + it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ + if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M0) { + uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->RDR); + dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->TDR); + uartp->rxbuf = 0; + } + + uartp->rxstate = UART_RX_IDLE; + uartp->txstate = UART_TX_IDLE; + usart_start(uartp); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_stop(UARTDriver *uartp) { + + if (uartp->state == UART_READY) { + usart_stop(uartp); + dmaStreamFreeI(uartp->dmarx); + dmaStreamFreeI(uartp->dmatx); + uartp->dmarx = NULL; + uartp->dmatx = NULL; + +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + rccDisableUSART1(); + return; + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + rccDisableUSART2(); + return; + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + rccDisableUSART3(); + return; + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + rccDisableUART4(); + return; + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + rccDisableUART5(); + return; + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + rccDisableUSART6(); + return; + } +#endif + +#if STM32_UART_USE_UART7 + if (&UARTD7 == uartp) { + rccDisableUART7(); + return; + } +#endif + +#if STM32_UART_USE_UART8 + if (&UARTD8 == uartp) { + rccDisableUART8(); + return; + } +#endif + } +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { + + /* TX DMA channel preparation.*/ + dmaStreamSetMemory0(uartp->dmatx, txbuf); + dmaStreamSetTransactionSize(uartp->dmatx, n); + dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Only enable TC interrupt if there's a callback attached to it or + if called from uartSendFullTimeout(). Also we need to clear TC flag + which could be set before.*/ +#if UART_USE_WAIT == TRUE + if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) { +#else + if (uartp->config->txend2_cb != NULL) { +#endif + uartp->usart->ICR = USART_ICR_TCCF; + uartp->usart->CR1 |= USART_CR1_TCIE; + } + + /* Starting transfer.*/ + dmaStreamEnable(uartp->dmatx); +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * + * @notapi + */ +size_t uart_lld_stop_send(UARTDriver *uartp) { + + dmaStreamDisable(uartp->dmatx); + + return dmaStreamGetTransactionSize(uartp->dmatx); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { + + /* Stopping previous activity (idle state).*/ + dmaStreamDisable(uartp->dmarx); + + /* RX DMA channel preparation.*/ + dmaStreamSetMemory0(uartp->dmarx, rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, n); + dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Starting transfer.*/ + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * + * @notapi + */ +size_t uart_lld_stop_receive(UARTDriver *uartp) { + size_t n; + + dmaStreamDisable(uartp->dmarx); + n = dmaStreamGetTransactionSize(uartp->dmarx); + uart_enter_rx_idle_loop(uartp); + + return n; +} + +/** + * @brief USART common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +void uart_lld_serve_interrupt(UARTDriver *uartp) { + uint32_t isr; + USART_TypeDef *u = uartp->usart; + uint32_t cr1 = u->CR1; + + /* Reading and clearing status.*/ + isr = u->ISR; + u->ICR = isr; + + if (isr & (USART_ISR_LBDF | USART_ISR_ORE | USART_ISR_NE | + USART_ISR_FE | USART_ISR_PE)) { + _uart_rx_error_isr_code(uartp, translate_errors(isr)); + } + + if ((isr & USART_ISR_TC) && (cr1 & USART_CR1_TCIE)) { + /* TC interrupt disabled.*/ + u->CR1 = cr1 & ~USART_CR1_TCIE; + + /* End of transmission, a callback is generated.*/ + _uart_tx2_isr_code(uartp); + } + + /* Timeout interrupt sources are only checked if enabled in CR1.*/ + if (((cr1 & USART_CR1_IDLEIE) && (isr & USART_ISR_IDLE)) || + ((cr1 & USART_CR1_RTOIE) && (isr & USART_ISR_RTOF))) { + _uart_timeout_isr_code(uartp); + } +} + +#endif /* HAL_USE_UART */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h b/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h index ec5a6949e7..a68beb90da 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h @@ -1,842 +1,842 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USARTv2/hal_uart_lld.h - * @brief STM32 low level UART driver header. - * - * @addtogroup UART - * @{ - */ - -#ifndef HAL_UART_LLD_H -#define HAL_UART_LLD_H - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief UART driver on USART1 enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART1 FALSE -#endif - -/** - * @brief UART driver on USART2 enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART2 FALSE -#endif - -/** - * @brief UART driver on USART3 enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART3 FALSE -#endif - -/** - * @brief UART driver on UART4 enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART4 FALSE -#endif - -/** - * @brief UART driver on UART5 enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART5 FALSE -#endif - -/** - * @brief UART driver on USART6 enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART6 FALSE -#endif - -/** - * @brief UART driver on UART7 enable switch. - * @details If set to @p TRUE the support for UART7 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART7 FALSE -#endif - -/** - * @brief UART driver on UART8 enable switch. - * @details If set to @p TRUE the support for UART8 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART8 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART4_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART5_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART7 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART7_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART8 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART8_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_DMA_PRIORITY 0 -#endif - -/** - * @brief USART2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_DMA_PRIORITY 0 -#endif - -/** - * @brief USART3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_DMA_PRIORITY 0 -#endif - -/** - * @brief UART4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART4_DMA_PRIORITY 0 -#endif - -/** - * @brief UART5 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART5_DMA_PRIORITY 0 -#endif - -/** - * @brief USART6 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART6_DMA_PRIORITY 0 -#endif - -/** - * @brief UART7 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART7_DMA_PRIORITY 0 -#endif - -/** - * @brief UART8 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART8_DMA_PRIORITY 0 -#endif - -/** - * @brief UART DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_UART_USE_UART4 && !STM32_HAS_UART4 -#error "UART4 not present in the selected device" -#endif - -#if STM32_UART_USE_UART5 && !STM32_HAS_UART5 -#error "UART5 not present in the selected device" -#endif - -#if STM32_UART_USE_UART7 && !STM32_HAS_UART7 -#error "UART7 not present in the selected device" -#endif - -#if STM32_UART_USE_UART8 && !STM32_HAS_UART8 -#error "UART8 not present in the selected device" -#endif - -#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ - !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ - !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \ - !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8 -#error "UART driver activated but no USART/UART peripheral assigned" -#endif - -#if !defined(STM32_USART1_SUPPRESS_ISR) && \ - STM32_UART_USE_USART1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if !defined(STM32_USART2_SUPPRESS_ISR) && \ - STM32_UART_USE_USART2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if !defined(STM32_USART3_SUPPRESS_ISR) && \ - STM32_UART_USE_USART3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if !defined(STM32_UART4_SUPPRESS_ISR) && \ - STM32_UART_USE_UART4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if !defined(STM32_UART5_SUPPRESS_ISR) && \ - STM32_UART_USE_UART5 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if !defined(STM32_USART6_SUPPRESS_ISR) && \ - STM32_UART_USE_USART6 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -#if !defined(STM32_UART7_SUPPRESS_ISR) && \ - STM32_UART_USE_UART7 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART7" -#endif - -#if !defined(STM32_UART8_SUPPRESS_ISR) && \ - STM32_UART_USE_UART8 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART8" -#endif - -/* Check on DMA priorities.*/ -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART3" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART4" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART5" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART6" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART7" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART8" -#endif - -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART1_TX_DMA_STREAM)) -#error "USART1 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART2_TX_DMA_STREAM)) -#error "USART2 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART3_TX_DMA_STREAM)) -#error "USART3 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART4_TX_DMA_STREAM)) -#error "UART4 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART5_TX_DMA_STREAM)) -#error "UART5 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART6_TX_DMA_STREAM)) -#error "USART6 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART7_TX_DMA_STREAM)) -#error "UART7 DMA streams not defined" -#endif - -#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \ - !defined(STM32_UART_UART8_TX_DMA_STREAM)) -#error "UART8 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART1 RX" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART1 TX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART2 RX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART2 TX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART3 RX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART3 TX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART4 RX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART4 TX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART5 RX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART5 TX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART6 RX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to USART6 TX" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART7 RX" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART7 TX" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_RX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART8 RX" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_TX_DMA_STREAM) -#error "Invalid DMA channel assigned to UART8 TX" -#endif - -/* Devices without DMAMUX require an additional check.*/ -#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_MSK) -#error "invalid DMA stream associated to USART1 RX" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_MSK) -#error "invalid DMA stream associated to USART1 TX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_MSK) -#error "invalid DMA stream associated to USART2 RX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_MSK) -#error "invalid DMA stream associated to USART2 TX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_MSK) -#error "invalid DMA stream associated to USART3 RX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_MSK) -#error "invalid DMA stream associated to USART3 TX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ - STM32_UART4_RX_DMA_MSK) -#error "invalid DMA stream associated to UART4 RX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ - STM32_UART4_TX_DMA_MSK) -#error "invalid DMA stream associated to UART4 TX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ - STM32_UART5_RX_DMA_MSK) -#error "invalid DMA stream associated to UART5 RX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ - STM32_UART5_TX_DMA_MSK) -#error "invalid DMA stream associated to UART5 TX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ - STM32_USART6_RX_DMA_MSK) -#error "invalid DMA stream associated to USART6 RX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ - STM32_USART6_TX_DMA_MSK) -#error "invalid DMA stream associated to USART6 TX" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \ - STM32_UART7_RX_DMA_MSK) -#error "invalid DMA stream associated to UART7 RX" -#endif - -#if STM32_UART_USE_UART7 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \ - STM32_UART7_TX_DMA_MSK) -#error "invalid DMA stream associated to UART7 TX" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \ - STM32_UART8_RX_DMA_MSK) -#error "invalid DMA stream associated to UART8 RX" -#endif - -#if STM32_UART_USE_UART8 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \ - STM32_UART8_TX_DMA_MSK) -#error "invalid DMA stream associated to UART8 TX" -#endif - -#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief UART driver condition flags type. - */ -typedef uint32_t uartflags_t; - -/** - * @brief Structure representing an UART driver. - */ -typedef struct UARTDriver UARTDriver; - -/** - * @brief Generic UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -typedef void (*uartcb_t)(UARTDriver *uartp); - -/** - * @brief Character received UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] c received character - */ -typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); - -/** - * @brief Receive error UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] e receive error mask - */ -typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief End of transmission buffer callback. - */ - uartcb_t txend1_cb; - /** - * @brief Physical end of transmission callback. - */ - uartcb_t txend2_cb; - /** - * @brief Receive buffer filled callback. - */ - uartcb_t rxend_cb; - /** - * @brief Character received while out if the @p UART_RECEIVE state. - */ - uartccb_t rxchar_cb; - /** - * @brief Receive error callback. - */ - uartecb_t rxerr_cb; - /* End of the mandatory fields.*/ - /** - * @brief Receiver timeout callback. - * @details Handles both idle and timeout interrupts depending on configured - * flags in CR registers and supported hardware features. - */ - uartcb_t timeout_cb; - /** - * @brief Receiver timeout value in terms of number of bit duration. - * @details Set it to 0 when you want to handle idle interrupt instead of - * hardware timeout. - */ - uint32_t timeout; - /** - * @brief Bit rate. - */ - uint32_t speed; - /** - * @brief Initialization value for the CR1 register. - */ - uint32_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint32_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint32_t cr3; -} UARTConfig; - -/** - * @brief Structure representing an UART driver. - */ -struct UARTDriver { - /** - * @brief Driver state. - */ - uartstate_t state; - /** - * @brief Transmitter state. - */ - uarttxstate_t txstate; - /** - * @brief Receiver state. - */ - uartrxstate_t rxstate; - /** - * @brief Current configuration data. - */ - const UARTConfig *config; -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) - /** - * @brief Synchronization flag for transmit operations. - */ - bool early; - /** - * @brief Waiting thread on RX. - */ - thread_reference_t threadrx; - /** - * @brief Waiting thread on TX. - */ - thread_reference_t threadtx; -#endif /* UART_USE_WAIT */ -#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the peripheral. - */ - mutex_t mutex; -#endif /* UART_USE_MUTUAL_EXCLUSION */ -#if defined(UART_DRIVER_EXT_FIELDS) - UART_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the USART registers block. - */ - USART_TypeDef *usart; - /** - * @brief Clock frequency for the associated USART/UART. - */ - uint32_t clock; - /** - * @brief Receive DMA mode bit mask. - */ - uint32_t dmarxmode; - /** - * @brief Send DMA mode bit mask. - */ - uint32_t dmatxmode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Default receive buffer while into @p UART_RX_IDLE state. - */ - volatile uint16_t rxbuf; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) -extern UARTDriver UARTD1; -#endif - -#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) -extern UARTDriver UARTD2; -#endif - -#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) -extern UARTDriver UARTD3; -#endif - -#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) -extern UARTDriver UARTD4; -#endif - -#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) -extern UARTDriver UARTD5; -#endif - -#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) -extern UARTDriver UARTD6; -#endif - -#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__) -extern UARTDriver UARTD7; -#endif - -#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__) -extern UARTDriver UARTD8; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void uart_lld_init(void); - void uart_lld_start(UARTDriver *uartp); - void uart_lld_stop(UARTDriver *uartp); - void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); - size_t uart_lld_stop_send(UARTDriver *uartp); - void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); - size_t uart_lld_stop_receive(UARTDriver *uartp); - void uart_lld_serve_interrupt(UARTDriver *uartp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_UART */ - -#endif /* HAL_UART_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv2/hal_uart_lld.h + * @brief STM32 low level UART driver header. + * + * @addtogroup UART + * @{ + */ + +#ifndef HAL_UART_LLD_H +#define HAL_UART_LLD_H + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief UART driver on USART1 enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART1 FALSE +#endif + +/** + * @brief UART driver on USART2 enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART2 FALSE +#endif + +/** + * @brief UART driver on USART3 enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART3 FALSE +#endif + +/** + * @brief UART driver on UART4 enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART4 FALSE +#endif + +/** + * @brief UART driver on UART5 enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART5 FALSE +#endif + +/** + * @brief UART driver on USART6 enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART6 FALSE +#endif + +/** + * @brief UART driver on UART7 enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART7 FALSE +#endif + +/** + * @brief UART driver on UART8 enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART8 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART7_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART8 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART8_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_DMA_PRIORITY 0 +#endif + +/** + * @brief USART2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_DMA_PRIORITY 0 +#endif + +/** + * @brief USART3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_DMA_PRIORITY 0 +#endif + +/** + * @brief UART4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_DMA_PRIORITY 0 +#endif + +/** + * @brief UART5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_DMA_PRIORITY 0 +#endif + +/** + * @brief USART6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_DMA_PRIORITY 0 +#endif + +/** + * @brief UART7 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART7_DMA_PRIORITY 0 +#endif + +/** + * @brief UART8 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART8_DMA_PRIORITY 0 +#endif + +/** + * @brief UART DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_UART_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_UART_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_UART_USE_UART7 && !STM32_HAS_UART7 +#error "UART7 not present in the selected device" +#endif + +#if STM32_UART_USE_UART8 && !STM32_HAS_UART8 +#error "UART8 not present in the selected device" +#endif + +#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ + !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ + !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \ + !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8 +#error "UART driver activated but no USART/UART peripheral assigned" +#endif + +#if !defined(STM32_USART1_SUPPRESS_ISR) && \ + STM32_UART_USE_USART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if !defined(STM32_USART2_SUPPRESS_ISR) && \ + STM32_UART_USE_USART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if !defined(STM32_USART3_SUPPRESS_ISR) && \ + STM32_UART_USE_USART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if !defined(STM32_UART4_SUPPRESS_ISR) && \ + STM32_UART_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if !defined(STM32_UART5_SUPPRESS_ISR) && \ + STM32_UART_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if !defined(STM32_USART6_SUPPRESS_ISR) && \ + STM32_UART_USE_USART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if !defined(STM32_UART7_SUPPRESS_ISR) && \ + STM32_UART_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +#if !defined(STM32_UART8_SUPPRESS_ISR) && \ + STM32_UART_USE_UART8 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART8" +#endif + +/* Check on DMA priorities.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART3" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART4" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART5" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART6" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART7" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART8" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART1_TX_DMA_STREAM)) +#error "USART1 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART2_TX_DMA_STREAM)) +#error "USART2 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART3_TX_DMA_STREAM)) +#error "USART3 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART4_TX_DMA_STREAM)) +#error "UART4 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART5_TX_DMA_STREAM)) +#error "UART5 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART6_TX_DMA_STREAM)) +#error "USART6 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART7_TX_DMA_STREAM)) +#error "UART7 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART8_TX_DMA_STREAM)) +#error "UART8 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART3 TX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART4 RX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART4 TX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART5 RX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART5 TX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART6 RX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART6 TX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART7 RX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART7 TX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART8 RX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART8 TX" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_MSK) +#error "invalid DMA stream associated to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_MSK) +#error "invalid DMA stream associated to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_MSK) +#error "invalid DMA stream associated to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_MSK) +#error "invalid DMA stream associated to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_MSK) +#error "invalid DMA stream associated to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_MSK) +#error "invalid DMA stream associated to USART3 TX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_MSK) +#error "invalid DMA stream associated to UART4 RX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_MSK) +#error "invalid DMA stream associated to UART4 TX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_MSK) +#error "invalid DMA stream associated to UART5 RX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_MSK) +#error "invalid DMA stream associated to UART5 TX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_MSK) +#error "invalid DMA stream associated to USART6 RX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_MSK) +#error "invalid DMA stream associated to USART6 TX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \ + STM32_UART7_RX_DMA_MSK) +#error "invalid DMA stream associated to UART7 RX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \ + STM32_UART7_TX_DMA_MSK) +#error "invalid DMA stream associated to UART7 TX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \ + STM32_UART8_RX_DMA_MSK) +#error "invalid DMA stream associated to UART8 RX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \ + STM32_UART8_TX_DMA_MSK) +#error "invalid DMA stream associated to UART8 TX" +#endif + +#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief UART driver condition flags type. + */ +typedef uint32_t uartflags_t; + +/** + * @brief Structure representing an UART driver. + */ +typedef struct UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief End of transmission buffer callback. + */ + uartcb_t txend1_cb; + /** + * @brief Physical end of transmission callback. + */ + uartcb_t txend2_cb; + /** + * @brief Receive buffer filled callback. + */ + uartcb_t rxend_cb; + /** + * @brief Character received while out if the @p UART_RECEIVE state. + */ + uartccb_t rxchar_cb; + /** + * @brief Receive error callback. + */ + uartecb_t rxerr_cb; + /* End of the mandatory fields.*/ + /** + * @brief Receiver timeout callback. + * @details Handles both idle and timeout interrupts depending on configured + * flags in CR registers and supported hardware features. + */ + uartcb_t timeout_cb; + /** + * @brief Receiver timeout value in terms of number of bit duration. + * @details Set it to 0 when you want to handle idle interrupt instead of + * hardware timeout. + */ + uint32_t timeout; + /** + * @brief Bit rate. + */ + uint32_t speed; + /** + * @brief Initialization value for the CR1 register. + */ + uint32_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint32_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint32_t cr3; +} UARTConfig; + +/** + * @brief Structure representing an UART driver. + */ +struct UARTDriver { + /** + * @brief Driver state. + */ + uartstate_t state; + /** + * @brief Transmitter state. + */ + uarttxstate_t txstate; + /** + * @brief Receiver state. + */ + uartrxstate_t rxstate; + /** + * @brief Current configuration data. + */ + const UARTConfig *config; +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Synchronization flag for transmit operations. + */ + bool early; + /** + * @brief Waiting thread on RX. + */ + thread_reference_t threadrx; + /** + * @brief Waiting thread on TX. + */ + thread_reference_t threadtx; +#endif /* UART_USE_WAIT */ +#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* UART_USE_MUTUAL_EXCLUSION */ +#if defined(UART_DRIVER_EXT_FIELDS) + UART_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the USART registers block. + */ + USART_TypeDef *usart; + /** + * @brief Clock frequency for the associated USART/UART. + */ + uint32_t clock; + /** + * @brief Receive DMA mode bit mask. + */ + uint32_t dmarxmode; + /** + * @brief Send DMA mode bit mask. + */ + uint32_t dmatxmode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Default receive buffer while into @p UART_RX_IDLE state. + */ + volatile uint16_t rxbuf; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) +extern UARTDriver UARTD1; +#endif + +#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) +extern UARTDriver UARTD2; +#endif + +#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) +extern UARTDriver UARTD3; +#endif + +#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) +extern UARTDriver UARTD4; +#endif + +#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) +extern UARTDriver UARTD5; +#endif + +#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) +extern UARTDriver UARTD6; +#endif + +#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__) +extern UARTDriver UARTD7; +#endif + +#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__) +extern UARTDriver UARTD8; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void uart_lld_init(void); + void uart_lld_start(UARTDriver *uartp); + void uart_lld_stop(UARTDriver *uartp); + void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); + size_t uart_lld_stop_send(UARTDriver *uartp); + void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uart_lld_stop_receive(UARTDriver *uartp); + void uart_lld_serve_interrupt(UARTDriver *uartp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART */ + +#endif /* HAL_UART_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USBv1/driver.mk b/os/hal/ports/STM32/LLD/USBv1/driver.mk index 1a6d862280..5d7811155f 100644 --- a/os/hal/ports/STM32/LLD/USBv1/driver.mk +++ b/os/hal/ports/STM32/LLD/USBv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1 diff --git a/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c b/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c index 9ca5c6a53a..6c53986832 100644 --- a/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c +++ b/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c @@ -1,874 +1,874 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USBv1/hal_usb_lld.c - * @brief STM32 USB subsystem low level driver source. - * - * @addtogroup USB - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_USB || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define BTABLE_ADDR 0x0000 - -#define EPR_EP_TYPE_IS_ISO(bits) ((bits & EPR_EP_TYPE_MASK) == EPR_EP_TYPE_ISO) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USB1 driver identifier.*/ -#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) -USBDriver USBD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief EP0 state. - * @note It is an union because IN and OUT endpoints are never used at the - * same time for EP0. - */ -static union { - /** - * @brief IN EP0 state. - */ - USBInEndpointState in; - /** - * @brief OUT EP0 state. - */ - USBOutEndpointState out; -} ep0_state; - -/** - * @brief Buffer for the EP0 setup packets. - */ -static uint8_t ep0setup_buffer[8]; - -/** - * @brief EP0 initialization structure. - */ -static const USBEndpointConfig ep0config = { - USB_EP_MODE_TYPE_CTRL, - _usb_ep0setup, - _usb_ep0in, - _usb_ep0out, - 0x40, - 0x40, - &ep0_state.in, - &ep0_state.out, - 1, - ep0setup_buffer -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Resets the packet memory allocator. - * - * @param[in] usbp pointer to the @p USBDriver object - */ -static void usb_pm_reset(USBDriver *usbp) { - - /* The first 64 bytes are reserved for the descriptors table. The effective - available RAM for endpoint buffers is just 448 bytes.*/ - usbp->pmnext = 64; -} - -/** - * @brief Resets the packet memory allocator. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] size size of the packet buffer to allocate - * @return The packet buffer address. - */ -static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) { - uint32_t next; - - next = usbp->pmnext; - usbp->pmnext += (size + 1) & ~1; - osalDbgAssert(usbp->pmnext <= STM32_USB_PMA_SIZE, "PMA overflow"); - return next; -} - -/** - * @brief Reads from a dedicated packet buffer. - * - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * @return The size of the receivee packet. - * - * @notapi - */ -static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) { - size_t i, n; - stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep); - stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->RXADDR0); -#if STM32_USB_USE_ISOCHRONOUS - uint32_t epr = STM32_USB->EPR[ep]; - - /* Double buffering is always enabled for isochronous endpoints, and - although we overlap the two buffers for simplicity, we still need - to read from the right counter. The DTOG_RX bit indicates the buffer - that is currently in use by the USB peripheral, that is, the buffer - in which the next received packet will be stored, so we need to - read the counter of the OTHER buffer, which is where the last - received packet was stored.*/ - if (EPR_EP_TYPE_IS_ISO(epr) && ((epr & EPR_DTOG_RX) != 0U)) - n = (size_t)udp->RXCOUNT1 & RXCOUNT_COUNT_MASK; - else - n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK; -#else - n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK; -#endif - - i = n; - -#if STM32_USB_USE_FAST_COPY - while (i >= 16) { - uint32_t w; - - w = *(pmap + 0); - *(buf + 0) = (uint8_t)w; - *(buf + 1) = (uint8_t)(w >> 8); - w = *(pmap + 1); - *(buf + 2) = (uint8_t)w; - *(buf + 3) = (uint8_t)(w >> 8); - w = *(pmap + 2); - *(buf + 4) = (uint8_t)w; - *(buf + 5) = (uint8_t)(w >> 8); - w = *(pmap + 3); - *(buf + 6) = (uint8_t)w; - *(buf + 7) = (uint8_t)(w >> 8); - w = *(pmap + 4); - *(buf + 8) = (uint8_t)w; - *(buf + 9) = (uint8_t)(w >> 8); - w = *(pmap + 5); - *(buf + 10) = (uint8_t)w; - *(buf + 11) = (uint8_t)(w >> 8); - w = *(pmap + 6); - *(buf + 12) = (uint8_t)w; - *(buf + 13) = (uint8_t)(w >> 8); - w = *(pmap + 7); - *(buf + 14) = (uint8_t)w; - *(buf + 15) = (uint8_t)(w >> 8); - - i -= 16; - buf += 16; - pmap += 8; - } -#endif /* STM32_USB_USE_FAST_COPY */ - - while (i >= 2) { - uint32_t w = *pmap++; - *buf++ = (uint8_t)w; - *buf++ = (uint8_t)(w >> 8); - i -= 2; - } - - if (i >= 1) { - *buf = (uint8_t)*pmap; - } - - return n; -} - -/** - * @brief Writes to a dedicated packet buffer. - * - * @param[in] ep endpoint number - * @param[in] buf buffer where to fetch the packet data - * @param[in] n maximum number of bytes to copy. This value must - * not exceed the maximum packet size for this endpoint. - * - * @notapi - */ -static void usb_packet_write_from_buffer(usbep_t ep, - const uint8_t *buf, - size_t n) { - stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep); - stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0); - int i = (int)n; - -#if STM32_USB_USE_ISOCHRONOUS - uint32_t epr = STM32_USB->EPR[ep]; - - /* Double buffering is always enabled for isochronous endpoints, and - although we overlap the two buffers for simplicity, we still need - to write to the right counter. The DTOG_TX bit indicates the buffer - that is currently in use by the USB peripheral, that is, the buffer - from which the next packet will be sent, so we need to write the - counter of that buffer.*/ - if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX)) - udp->TXCOUNT1 = (stm32_usb_pma_t)n; - else - udp->TXCOUNT0 = (stm32_usb_pma_t)n; -#else - udp->TXCOUNT0 = (stm32_usb_pma_t)n; -#endif - -#if STM32_USB_USE_FAST_COPY - while (i >= 16) { - uint32_t w; - - w = *(buf + 0); - w |= *(buf + 1) << 8; - *(pmap + 0) = (stm32_usb_pma_t)w; - w = *(buf + 2); - w |= *(buf + 3) << 8; - *(pmap + 1) = (stm32_usb_pma_t)w; - w = *(buf + 4); - w |= *(buf + 5) << 8; - *(pmap + 2) = (stm32_usb_pma_t)w; - w = *(buf + 6); - w |= *(buf + 7) << 8; - *(pmap + 3) = (stm32_usb_pma_t)w; - w = *(buf + 8); - w |= *(buf + 9) << 8; - *(pmap + 4) = (stm32_usb_pma_t)w; - w = *(buf + 10); - w |= *(buf + 11) << 8; - *(pmap + 5) = (stm32_usb_pma_t)w; - w = *(buf + 12); - w |= *(buf + 13) << 8; - *(pmap + 6) = (stm32_usb_pma_t)w; - w = *(buf + 14); - w |= *(buf + 15) << 8; - *(pmap + 7) = (stm32_usb_pma_t)w; - - i -= 16; - buf += 16; - pmap += 8; - } -#endif /* STM32_USB_USE_FAST_COPY */ - - while (i > 0) { - uint32_t w; - - w = *buf++; - w |= *buf++ << 8; - *pmap++ = (stm32_usb_pma_t)w; - i -= 2; - } -} - -/** - * @brief Common ISR code, serves the EP-related interrupts. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) { - size_t n; - uint32_t epr = STM32_USB->EPR[ep]; - const USBEndpointConfig *epcp = usbp->epc[ep]; - - if (epr & EPR_CTR_TX) { - /* IN endpoint, transmission.*/ - USBInEndpointState *isp = epcp->in_state; - - EPR_CLEAR_CTR_TX(ep); - - isp->txcnt += isp->txlast; - n = isp->txsize - isp->txcnt; - if (n > 0) { - /* Transfer not completed, there are more packets to send.*/ - if (n > epcp->in_maxsize) - n = epcp->in_maxsize; - - /* Writes the packet from the defined buffer.*/ - isp->txbuf += isp->txlast; - isp->txlast = n; - usb_packet_write_from_buffer(ep, isp->txbuf, n); - - /* Starting IN operation.*/ - EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); - } - else { - /* Transfer completed, invokes the callback.*/ - _usb_isr_invoke_in_cb(usbp, ep); - } - } - if (epr & EPR_CTR_RX) { - /* OUT endpoint, receive.*/ - - EPR_CLEAR_CTR_RX(ep); - - if (epr & EPR_SETUP) { - /* Setup packets handling, setup packets are handled using a - specific callback.*/ - _usb_isr_invoke_setup_cb(usbp, ep); - } - else { - USBOutEndpointState *osp = epcp->out_state; - - /* Reads the packet into the defined buffer.*/ - n = usb_packet_read_to_buffer(ep, osp->rxbuf); - osp->rxbuf += n; - - /* Transaction data updated.*/ - osp->rxcnt += n; - osp->rxsize -= n; - osp->rxpkts -= 1; - - /* The transaction is completed if the specified number of packets - has been received or the current packet is a short packet.*/ - if ((n < epcp->out_maxsize) || (osp->rxpkts == 0)) { - /* Transfer complete, invokes the callback.*/ - _usb_isr_invoke_out_cb(usbp, ep); - } - else { - /* Transfer not complete, there are more packets to receive.*/ - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) -#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER -#if STM32_USB_USE_ISOCHRONOUS -/** - * @brief USB high priority interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USB1_HP_HANDLER) { - uint32_t istr; - USBDriver *usbp = &USBD1; - - OSAL_IRQ_PROLOGUE(); - - /* Endpoint events handling.*/ - istr = STM32_USB->ISTR; - while (istr & ISTR_CTR) { - usb_serve_endpoints(usbp, istr & ISTR_EP_ID_MASK); - istr = STM32_USB->ISTR; - } - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_USB_USE_ISOCHRONOUS */ -#endif /* STM32_USB1_LP_NUMBER != STM32_USB1_HP_NUMBER */ - -/** - * @brief USB low priority interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USB1_LP_HANDLER) { - uint32_t istr; - USBDriver *usbp = &USBD1; - - OSAL_IRQ_PROLOGUE(); - - istr = STM32_USB->ISTR; - - /* USB bus reset condition handling.*/ - if (istr & ISTR_RESET) { - STM32_USB->ISTR = ~ISTR_RESET; - - _usb_reset(usbp); - } - - /* USB bus SUSPEND condition handling.*/ - if (istr & ISTR_SUSP) { - STM32_USB->CNTR |= CNTR_FSUSP; -#if STM32_USB_LOW_POWER_ON_SUSPEND - STM32_USB->CNTR |= CNTR_LP_MODE; -#endif - STM32_USB->ISTR = ~ISTR_SUSP; - - _usb_suspend(usbp); - } - - /* USB bus WAKEUP condition handling.*/ - if (istr & ISTR_WKUP) { - uint32_t fnr = STM32_USB->FNR; - if (!(fnr & FNR_RXDP)) { - STM32_USB->CNTR &= ~CNTR_FSUSP; - - _usb_wakeup(usbp); - } -#if STM32_USB_LOW_POWER_ON_SUSPEND - else { - /* Just noise, going back in SUSPEND mode, reference manual 22.4.5, - table 169.*/ - STM32_USB->CNTR |= CNTR_LP_MODE; - } -#endif - STM32_USB->ISTR = ~ISTR_WKUP; - } - - /* SOF handling.*/ - if (istr & ISTR_SOF) { - _usb_isr_invoke_sof_cb(usbp); - STM32_USB->ISTR = ~ISTR_SOF; - } - - /* Endpoint events handling.*/ - while (istr & ISTR_CTR) { - usb_serve_endpoints(usbp, istr & ISTR_EP_ID_MASK); - istr = STM32_USB->ISTR; - } - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_USB_USE_USB1 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level USB driver initialization. - * - * @notapi - */ -void usb_lld_init(void) { - - /* Driver initialization.*/ - usbObjectInit(&USBD1); -} - -/** - * @brief Configures and activates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_start(USBDriver *usbp) { - - if (usbp->state == USB_STOP) { - /* Clock activation.*/ -#if STM32_USB_USE_USB1 - if (&USBD1 == usbp) { - /* USB clock enabled.*/ - rccEnableUSB(true); - /* Powers up the transceiver while holding the USB in reset state.*/ - STM32_USB->CNTR = CNTR_FRES; - /* Enabling the USB IRQ vectors, this also gives enough time to allow - the transceiver power up (1uS).*/ -#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER - nvicEnableVector(STM32_USB1_HP_NUMBER, STM32_USB_USB1_HP_IRQ_PRIORITY); -#endif - nvicEnableVector(STM32_USB1_LP_NUMBER, STM32_USB_USB1_LP_IRQ_PRIORITY); - /* Releases the USB reset.*/ - STM32_USB->CNTR = 0; - } -#endif - /* Reset procedure enforced on driver start.*/ - usb_lld_reset(usbp); - } -} - -/** - * @brief Deactivates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_stop(USBDriver *usbp) { - - /* If in ready state then disables the USB clock.*/ - if (usbp->state != USB_STOP) { -#if STM32_USB_USE_USB1 - if (&USBD1 == usbp) { -#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER - nvicDisableVector(STM32_USB1_HP_NUMBER); -#endif - nvicDisableVector(STM32_USB1_LP_NUMBER); - STM32_USB->CNTR = CNTR_PDWN | CNTR_FRES; - rccDisableUSB(); - } -#endif - } -} - -/** - * @brief USB low level reset routine. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_reset(USBDriver *usbp) { - uint32_t cntr; - - /* Post reset initialization.*/ - STM32_USB->BTABLE = BTABLE_ADDR; - STM32_USB->ISTR = 0; - STM32_USB->DADDR = DADDR_EF; - cntr = /*CNTR_ESOFM | */ CNTR_RESETM | CNTR_SUSPM | - CNTR_WKUPM | /*CNTR_ERRM | CNTR_PMAOVRM |*/ CNTR_CTRM; - /* The SOF interrupt is only enabled if a callback is defined for - this service because it is an high rate source.*/ - if (usbp->config->sof_cb != NULL) - cntr |= CNTR_SOFM; - STM32_USB->CNTR = cntr; - - /* Resets the packet memory allocator.*/ - usb_pm_reset(usbp); - - /* EP0 initialization.*/ - usbp->epc[0] = &ep0config; - usb_lld_init_endpoint(usbp, 0); -} - -/** - * @brief Sets the USB address. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_set_address(USBDriver *usbp) { - - STM32_USB->DADDR = (uint32_t)(usbp->address) | DADDR_EF; -} - -/** - * @brief Enables an endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { - uint16_t epr; - stm32_usb_descriptor_t *dp; - const USBEndpointConfig *epcp = usbp->epc[ep]; - - /* Setting the endpoint type. Note that isochronous endpoints cannot be - bidirectional because it uses double buffering and both transmit and - receive descriptor fields are used for either direction.*/ - switch (epcp->ep_mode & USB_EP_MODE_TYPE) { - case USB_EP_MODE_TYPE_ISOC: -#if STM32_USB_USE_ISOCHRONOUS - osalDbgAssert((epcp->in_state == NULL) || (epcp->out_state == NULL), - "isochronous EP cannot be IN and OUT"); - epr = EPR_EP_TYPE_ISO; - break; -#else - osalDbgAssert(false, "isochronous support disabled"); -#endif - /* Falls through.*/ - case USB_EP_MODE_TYPE_BULK: - epr = EPR_EP_TYPE_BULK; - break; - case USB_EP_MODE_TYPE_INTR: - epr = EPR_EP_TYPE_INTERRUPT; - break; - default: - epr = EPR_EP_TYPE_CONTROL; - } - - dp = USB_GET_DESCRIPTOR(ep); - - /* IN endpoint handling.*/ - if (epcp->in_state != NULL) { - dp->TXCOUNT0 = 0; - dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); - -#if STM32_USB_USE_ISOCHRONOUS - if (epr == EPR_EP_TYPE_ISO) { - epr |= EPR_STAT_TX_VALID; - dp->TXCOUNT1 = dp->TXCOUNT0; - dp->TXADDR1 = dp->TXADDR0; /* Both buffers overlapped.*/ - } - else { - epr |= EPR_STAT_TX_NAK; - } -#else - epr |= EPR_STAT_TX_NAK; -#endif - } - - /* OUT endpoint handling.*/ - if (epcp->out_state != NULL) { - uint16_t nblocks; - - /* Endpoint size and address initialization.*/ - if (epcp->out_maxsize > 62) - nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | - 0x8000; - else - nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; - dp->RXCOUNT0 = nblocks; - dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); - -#if STM32_USB_USE_ISOCHRONOUS - if (epr == EPR_EP_TYPE_ISO) { - epr |= EPR_STAT_RX_VALID; - dp->RXCOUNT1 = dp->RXCOUNT0; - dp->RXADDR1 = dp->RXADDR0; /* Both buffers overlapped.*/ - } - else { - epr |= EPR_STAT_RX_NAK; - } -#else - epr |= EPR_STAT_RX_NAK; -#endif - } - - /* Resetting the data toggling bits for this endpoint.*/ - if (STM32_USB->EPR[ep] & EPR_DTOG_RX) { - epr |= EPR_DTOG_RX; - } - - if (STM32_USB->EPR[ep] & EPR_DTOG_TX) { - epr |= EPR_DTOG_TX; - } - - /* EPxR register setup.*/ - EPR_SET(ep, epr | ep); - EPR_TOGGLE(ep, epr); -} - -/** - * @brief Disables all the active endpoints except the endpoint zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_disable_endpoints(USBDriver *usbp) { - unsigned i; - - /* Resets the packet memory allocator.*/ - usb_pm_reset(usbp); - - /* Disabling all endpoints.*/ - for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) { - EPR_TOGGLE(i, 0); - EPR_SET(i, 0); - } -} - -/** - * @brief Returns the status of an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - switch (STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) { - case EPR_STAT_RX_DIS: - return EP_STATUS_DISABLED; - case EPR_STAT_RX_STALL: - return EP_STATUS_STALLED; - default: - return EP_STATUS_ACTIVE; - } -} - -/** - * @brief Returns the status of an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - switch (STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) { - case EPR_STAT_TX_DIS: - return EP_STATUS_DISABLED; - case EPR_STAT_TX_STALL: - return EP_STATUS_STALLED; - default: - return EP_STATUS_ACTIVE; - } -} - -/** - * @brief Reads a setup packet from the dedicated packet buffer. - * @details This function must be invoked in the context of the @p setup_cb - * callback in order to read the received setup packet. - * @pre In order to use this function the endpoint must have been - * initialized as a control endpoint. - * @post The endpoint is ready to accept another packet. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * - * @notapi - */ -void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { - stm32_usb_pma_t *pmap; - stm32_usb_descriptor_t *udp; - uint32_t n; - - (void)usbp; - udp = USB_GET_DESCRIPTOR(ep); - pmap = USB_ADDR2PTR(udp->RXADDR0); - for (n = 0; n < 4; n++) { - *(uint16_t *)buf = (uint16_t)*pmap++; - buf += 2; - } -} - -/** - * @brief Starts a receive operation on an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - /* Transfer initialization.*/ - if (osp->rxsize == 0) /* Special case for zero sized packets.*/ - osp->rxpkts = 1; - else - osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / - usbp->epc[ep]->out_maxsize); - - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); -} - -/** - * @brief Starts a transmit operation on an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { - size_t n; - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - /* Transfer initialization.*/ - n = isp->txsize; - if (n > (size_t)usbp->epc[ep]->in_maxsize) - n = (size_t)usbp->epc[ep]->in_maxsize; - - isp->txlast = n; - usb_packet_write_from_buffer(ep, isp->txbuf, n); - - EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); -} - -/** - * @brief Brings an OUT endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); -} - -/** - * @brief Brings an IN endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - EPR_SET_STAT_TX(ep, EPR_STAT_TX_STALL); -} - -/** - * @brief Brings an OUT endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - /* Makes sure to not put to NAK an endpoint that is already - transferring.*/ - if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_VALID) - EPR_SET_STAT_TX(ep, EPR_STAT_RX_NAK); -} - -/** - * @brief Brings an IN endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - /* Makes sure to not put to NAK an endpoint that is already - transferring.*/ - if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_VALID) - EPR_SET_STAT_TX(ep, EPR_STAT_TX_NAK); -} - -#endif /* HAL_USE_USB */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USBv1/hal_usb_lld.c + * @brief STM32 USB subsystem low level driver source. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define BTABLE_ADDR 0x0000 + +#define EPR_EP_TYPE_IS_ISO(bits) ((bits & EPR_EP_TYPE_MASK) == EPR_EP_TYPE_ISO) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USB1 driver identifier.*/ +#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + * @note It is an union because IN and OUT endpoints are never used at the + * same time for EP0. + */ +static union { + /** + * @brief IN EP0 state. + */ + USBInEndpointState in; + /** + * @brief OUT EP0 state. + */ + USBOutEndpointState out; +} ep0_state; + +/** + * @brief Buffer for the EP0 setup packets. + */ +static uint8_t ep0setup_buffer[8]; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + USB_EP_MODE_TYPE_CTRL, + _usb_ep0setup, + _usb_ep0in, + _usb_ep0out, + 0x40, + 0x40, + &ep0_state.in, + &ep0_state.out, + 1, + ep0setup_buffer +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Resets the packet memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + */ +static void usb_pm_reset(USBDriver *usbp) { + + /* The first 64 bytes are reserved for the descriptors table. The effective + available RAM for endpoint buffers is just 448 bytes.*/ + usbp->pmnext = 64; +} + +/** + * @brief Resets the packet memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] size size of the packet buffer to allocate + * @return The packet buffer address. + */ +static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) { + uint32_t next; + + next = usbp->pmnext; + usbp->pmnext += (size + 1) & ~1; + osalDbgAssert(usbp->pmnext <= STM32_USB_PMA_SIZE, "PMA overflow"); + return next; +} + +/** + * @brief Reads from a dedicated packet buffer. + * + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * @return The size of the receivee packet. + * + * @notapi + */ +static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) { + size_t i, n; + stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep); + stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->RXADDR0); +#if STM32_USB_USE_ISOCHRONOUS + uint32_t epr = STM32_USB->EPR[ep]; + + /* Double buffering is always enabled for isochronous endpoints, and + although we overlap the two buffers for simplicity, we still need + to read from the right counter. The DTOG_RX bit indicates the buffer + that is currently in use by the USB peripheral, that is, the buffer + in which the next received packet will be stored, so we need to + read the counter of the OTHER buffer, which is where the last + received packet was stored.*/ + if (EPR_EP_TYPE_IS_ISO(epr) && ((epr & EPR_DTOG_RX) != 0U)) + n = (size_t)udp->RXCOUNT1 & RXCOUNT_COUNT_MASK; + else + n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK; +#else + n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK; +#endif + + i = n; + +#if STM32_USB_USE_FAST_COPY + while (i >= 16) { + uint32_t w; + + w = *(pmap + 0); + *(buf + 0) = (uint8_t)w; + *(buf + 1) = (uint8_t)(w >> 8); + w = *(pmap + 1); + *(buf + 2) = (uint8_t)w; + *(buf + 3) = (uint8_t)(w >> 8); + w = *(pmap + 2); + *(buf + 4) = (uint8_t)w; + *(buf + 5) = (uint8_t)(w >> 8); + w = *(pmap + 3); + *(buf + 6) = (uint8_t)w; + *(buf + 7) = (uint8_t)(w >> 8); + w = *(pmap + 4); + *(buf + 8) = (uint8_t)w; + *(buf + 9) = (uint8_t)(w >> 8); + w = *(pmap + 5); + *(buf + 10) = (uint8_t)w; + *(buf + 11) = (uint8_t)(w >> 8); + w = *(pmap + 6); + *(buf + 12) = (uint8_t)w; + *(buf + 13) = (uint8_t)(w >> 8); + w = *(pmap + 7); + *(buf + 14) = (uint8_t)w; + *(buf + 15) = (uint8_t)(w >> 8); + + i -= 16; + buf += 16; + pmap += 8; + } +#endif /* STM32_USB_USE_FAST_COPY */ + + while (i >= 2) { + uint32_t w = *pmap++; + *buf++ = (uint8_t)w; + *buf++ = (uint8_t)(w >> 8); + i -= 2; + } + + if (i >= 1) { + *buf = (uint8_t)*pmap; + } + + return n; +} + +/** + * @brief Writes to a dedicated packet buffer. + * + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * + * @notapi + */ +static void usb_packet_write_from_buffer(usbep_t ep, + const uint8_t *buf, + size_t n) { + stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep); + stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0); + int i = (int)n; + +#if STM32_USB_USE_ISOCHRONOUS + uint32_t epr = STM32_USB->EPR[ep]; + + /* Double buffering is always enabled for isochronous endpoints, and + although we overlap the two buffers for simplicity, we still need + to write to the right counter. The DTOG_TX bit indicates the buffer + that is currently in use by the USB peripheral, that is, the buffer + from which the next packet will be sent, so we need to write the + counter of that buffer.*/ + if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX)) + udp->TXCOUNT1 = (stm32_usb_pma_t)n; + else + udp->TXCOUNT0 = (stm32_usb_pma_t)n; +#else + udp->TXCOUNT0 = (stm32_usb_pma_t)n; +#endif + +#if STM32_USB_USE_FAST_COPY + while (i >= 16) { + uint32_t w; + + w = *(buf + 0); + w |= *(buf + 1) << 8; + *(pmap + 0) = (stm32_usb_pma_t)w; + w = *(buf + 2); + w |= *(buf + 3) << 8; + *(pmap + 1) = (stm32_usb_pma_t)w; + w = *(buf + 4); + w |= *(buf + 5) << 8; + *(pmap + 2) = (stm32_usb_pma_t)w; + w = *(buf + 6); + w |= *(buf + 7) << 8; + *(pmap + 3) = (stm32_usb_pma_t)w; + w = *(buf + 8); + w |= *(buf + 9) << 8; + *(pmap + 4) = (stm32_usb_pma_t)w; + w = *(buf + 10); + w |= *(buf + 11) << 8; + *(pmap + 5) = (stm32_usb_pma_t)w; + w = *(buf + 12); + w |= *(buf + 13) << 8; + *(pmap + 6) = (stm32_usb_pma_t)w; + w = *(buf + 14); + w |= *(buf + 15) << 8; + *(pmap + 7) = (stm32_usb_pma_t)w; + + i -= 16; + buf += 16; + pmap += 8; + } +#endif /* STM32_USB_USE_FAST_COPY */ + + while (i > 0) { + uint32_t w; + + w = *buf++; + w |= *buf++ << 8; + *pmap++ = (stm32_usb_pma_t)w; + i -= 2; + } +} + +/** + * @brief Common ISR code, serves the EP-related interrupts. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) { + size_t n; + uint32_t epr = STM32_USB->EPR[ep]; + const USBEndpointConfig *epcp = usbp->epc[ep]; + + if (epr & EPR_CTR_TX) { + /* IN endpoint, transmission.*/ + USBInEndpointState *isp = epcp->in_state; + + EPR_CLEAR_CTR_TX(ep); + + isp->txcnt += isp->txlast; + n = isp->txsize - isp->txcnt; + if (n > 0) { + /* Transfer not completed, there are more packets to send.*/ + if (n > epcp->in_maxsize) + n = epcp->in_maxsize; + + /* Writes the packet from the defined buffer.*/ + isp->txbuf += isp->txlast; + isp->txlast = n; + usb_packet_write_from_buffer(ep, isp->txbuf, n); + + /* Starting IN operation.*/ + EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); + } + else { + /* Transfer completed, invokes the callback.*/ + _usb_isr_invoke_in_cb(usbp, ep); + } + } + if (epr & EPR_CTR_RX) { + /* OUT endpoint, receive.*/ + + EPR_CLEAR_CTR_RX(ep); + + if (epr & EPR_SETUP) { + /* Setup packets handling, setup packets are handled using a + specific callback.*/ + _usb_isr_invoke_setup_cb(usbp, ep); + } + else { + USBOutEndpointState *osp = epcp->out_state; + + /* Reads the packet into the defined buffer.*/ + n = usb_packet_read_to_buffer(ep, osp->rxbuf); + osp->rxbuf += n; + + /* Transaction data updated.*/ + osp->rxcnt += n; + osp->rxsize -= n; + osp->rxpkts -= 1; + + /* The transaction is completed if the specified number of packets + has been received or the current packet is a short packet.*/ + if ((n < epcp->out_maxsize) || (osp->rxpkts == 0)) { + /* Transfer complete, invokes the callback.*/ + _usb_isr_invoke_out_cb(usbp, ep); + } + else { + /* Transfer not complete, there are more packets to receive.*/ + EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) +#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER +#if STM32_USB_USE_ISOCHRONOUS +/** + * @brief USB high priority interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USB1_HP_HANDLER) { + uint32_t istr; + USBDriver *usbp = &USBD1; + + OSAL_IRQ_PROLOGUE(); + + /* Endpoint events handling.*/ + istr = STM32_USB->ISTR; + while (istr & ISTR_CTR) { + usb_serve_endpoints(usbp, istr & ISTR_EP_ID_MASK); + istr = STM32_USB->ISTR; + } + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_USB_USE_ISOCHRONOUS */ +#endif /* STM32_USB1_LP_NUMBER != STM32_USB1_HP_NUMBER */ + +/** + * @brief USB low priority interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USB1_LP_HANDLER) { + uint32_t istr; + USBDriver *usbp = &USBD1; + + OSAL_IRQ_PROLOGUE(); + + istr = STM32_USB->ISTR; + + /* USB bus reset condition handling.*/ + if (istr & ISTR_RESET) { + STM32_USB->ISTR = ~ISTR_RESET; + + _usb_reset(usbp); + } + + /* USB bus SUSPEND condition handling.*/ + if (istr & ISTR_SUSP) { + STM32_USB->CNTR |= CNTR_FSUSP; +#if STM32_USB_LOW_POWER_ON_SUSPEND + STM32_USB->CNTR |= CNTR_LP_MODE; +#endif + STM32_USB->ISTR = ~ISTR_SUSP; + + _usb_suspend(usbp); + } + + /* USB bus WAKEUP condition handling.*/ + if (istr & ISTR_WKUP) { + uint32_t fnr = STM32_USB->FNR; + if (!(fnr & FNR_RXDP)) { + STM32_USB->CNTR &= ~CNTR_FSUSP; + + _usb_wakeup(usbp); + } +#if STM32_USB_LOW_POWER_ON_SUSPEND + else { + /* Just noise, going back in SUSPEND mode, reference manual 22.4.5, + table 169.*/ + STM32_USB->CNTR |= CNTR_LP_MODE; + } +#endif + STM32_USB->ISTR = ~ISTR_WKUP; + } + + /* SOF handling.*/ + if (istr & ISTR_SOF) { + _usb_isr_invoke_sof_cb(usbp); + STM32_USB->ISTR = ~ISTR_SOF; + } + + /* Endpoint events handling.*/ + while (istr & ISTR_CTR) { + usb_serve_endpoints(usbp, istr & ISTR_EP_ID_MASK); + istr = STM32_USB->ISTR; + } + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_USB_USE_USB1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { + + /* Driver initialization.*/ + usbObjectInit(&USBD1); +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { + + if (usbp->state == USB_STOP) { + /* Clock activation.*/ +#if STM32_USB_USE_USB1 + if (&USBD1 == usbp) { + /* USB clock enabled.*/ + rccEnableUSB(true); + /* Powers up the transceiver while holding the USB in reset state.*/ + STM32_USB->CNTR = CNTR_FRES; + /* Enabling the USB IRQ vectors, this also gives enough time to allow + the transceiver power up (1uS).*/ +#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER + nvicEnableVector(STM32_USB1_HP_NUMBER, STM32_USB_USB1_HP_IRQ_PRIORITY); +#endif + nvicEnableVector(STM32_USB1_LP_NUMBER, STM32_USB_USB1_LP_IRQ_PRIORITY); + /* Releases the USB reset.*/ + STM32_USB->CNTR = 0; + } +#endif + /* Reset procedure enforced on driver start.*/ + usb_lld_reset(usbp); + } +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { + + /* If in ready state then disables the USB clock.*/ + if (usbp->state != USB_STOP) { +#if STM32_USB_USE_USB1 + if (&USBD1 == usbp) { +#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER + nvicDisableVector(STM32_USB1_HP_NUMBER); +#endif + nvicDisableVector(STM32_USB1_LP_NUMBER); + STM32_USB->CNTR = CNTR_PDWN | CNTR_FRES; + rccDisableUSB(); + } +#endif + } +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + uint32_t cntr; + + /* Post reset initialization.*/ + STM32_USB->BTABLE = BTABLE_ADDR; + STM32_USB->ISTR = 0; + STM32_USB->DADDR = DADDR_EF; + cntr = /*CNTR_ESOFM | */ CNTR_RESETM | CNTR_SUSPM | + CNTR_WKUPM | /*CNTR_ERRM | CNTR_PMAOVRM |*/ CNTR_CTRM; + /* The SOF interrupt is only enabled if a callback is defined for + this service because it is an high rate source.*/ + if (usbp->config->sof_cb != NULL) + cntr |= CNTR_SOFM; + STM32_USB->CNTR = cntr; + + /* Resets the packet memory allocator.*/ + usb_pm_reset(usbp); + + /* EP0 initialization.*/ + usbp->epc[0] = &ep0config; + usb_lld_init_endpoint(usbp, 0); +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + + STM32_USB->DADDR = (uint32_t)(usbp->address) | DADDR_EF; +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + uint16_t epr; + stm32_usb_descriptor_t *dp; + const USBEndpointConfig *epcp = usbp->epc[ep]; + + /* Setting the endpoint type. Note that isochronous endpoints cannot be + bidirectional because it uses double buffering and both transmit and + receive descriptor fields are used for either direction.*/ + switch (epcp->ep_mode & USB_EP_MODE_TYPE) { + case USB_EP_MODE_TYPE_ISOC: +#if STM32_USB_USE_ISOCHRONOUS + osalDbgAssert((epcp->in_state == NULL) || (epcp->out_state == NULL), + "isochronous EP cannot be IN and OUT"); + epr = EPR_EP_TYPE_ISO; + break; +#else + osalDbgAssert(false, "isochronous support disabled"); +#endif + /* Falls through.*/ + case USB_EP_MODE_TYPE_BULK: + epr = EPR_EP_TYPE_BULK; + break; + case USB_EP_MODE_TYPE_INTR: + epr = EPR_EP_TYPE_INTERRUPT; + break; + default: + epr = EPR_EP_TYPE_CONTROL; + } + + dp = USB_GET_DESCRIPTOR(ep); + + /* IN endpoint handling.*/ + if (epcp->in_state != NULL) { + dp->TXCOUNT0 = 0; + dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); + +#if STM32_USB_USE_ISOCHRONOUS + if (epr == EPR_EP_TYPE_ISO) { + epr |= EPR_STAT_TX_VALID; + dp->TXCOUNT1 = dp->TXCOUNT0; + dp->TXADDR1 = dp->TXADDR0; /* Both buffers overlapped.*/ + } + else { + epr |= EPR_STAT_TX_NAK; + } +#else + epr |= EPR_STAT_TX_NAK; +#endif + } + + /* OUT endpoint handling.*/ + if (epcp->out_state != NULL) { + uint16_t nblocks; + + /* Endpoint size and address initialization.*/ + if (epcp->out_maxsize > 62) + nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | + 0x8000; + else + nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; + dp->RXCOUNT0 = nblocks; + dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); + +#if STM32_USB_USE_ISOCHRONOUS + if (epr == EPR_EP_TYPE_ISO) { + epr |= EPR_STAT_RX_VALID; + dp->RXCOUNT1 = dp->RXCOUNT0; + dp->RXADDR1 = dp->RXADDR0; /* Both buffers overlapped.*/ + } + else { + epr |= EPR_STAT_RX_NAK; + } +#else + epr |= EPR_STAT_RX_NAK; +#endif + } + + /* Resetting the data toggling bits for this endpoint.*/ + if (STM32_USB->EPR[ep] & EPR_DTOG_RX) { + epr |= EPR_DTOG_RX; + } + + if (STM32_USB->EPR[ep] & EPR_DTOG_TX) { + epr |= EPR_DTOG_TX; + } + + /* EPxR register setup.*/ + EPR_SET(ep, epr | ep); + EPR_TOGGLE(ep, epr); +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + unsigned i; + + /* Resets the packet memory allocator.*/ + usb_pm_reset(usbp); + + /* Disabling all endpoints.*/ + for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) { + EPR_TOGGLE(i, 0); + EPR_SET(i, 0); + } +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + switch (STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) { + case EPR_STAT_RX_DIS: + return EP_STATUS_DISABLED; + case EPR_STAT_RX_STALL: + return EP_STATUS_STALLED; + default: + return EP_STATUS_ACTIVE; + } +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + switch (STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) { + case EPR_STAT_TX_DIS: + return EP_STATUS_DISABLED; + case EPR_STAT_TX_STALL: + return EP_STATUS_STALLED; + default: + return EP_STATUS_ACTIVE; + } +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + stm32_usb_pma_t *pmap; + stm32_usb_descriptor_t *udp; + uint32_t n; + + (void)usbp; + udp = USB_GET_DESCRIPTOR(ep); + pmap = USB_ADDR2PTR(udp->RXADDR0); + for (n = 0; n < 4; n++) { + *(uint16_t *)buf = (uint16_t)*pmap++; + buf += 2; + } +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + + /* Transfer initialization.*/ + if (osp->rxsize == 0) /* Special case for zero sized packets.*/ + osp->rxpkts = 1; + else + osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / + usbp->epc[ep]->out_maxsize); + + EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + size_t n; + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + /* Transfer initialization.*/ + n = isp->txsize; + if (n > (size_t)usbp->epc[ep]->in_maxsize) + n = (size_t)usbp->epc[ep]->in_maxsize; + + isp->txlast = n; + usb_packet_write_from_buffer(ep, isp->txbuf, n); + + EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_TX(ep, EPR_STAT_TX_STALL); +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + /* Makes sure to not put to NAK an endpoint that is already + transferring.*/ + if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_VALID) + EPR_SET_STAT_TX(ep, EPR_STAT_RX_NAK); +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + /* Makes sure to not put to NAK an endpoint that is already + transferring.*/ + if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_VALID) + EPR_SET_STAT_TX(ep, EPR_STAT_TX_NAK); +} + +#endif /* HAL_USE_USB */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h b/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h index 1270172fc4..83c369ea8d 100644 --- a/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h +++ b/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h @@ -1,521 +1,521 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USBv1/hal_usb_lld.h - * @brief STM32 USB subsystem low level driver header. - * - * @addtogroup USB - * @{ - */ - -#ifndef HAL_USB_LLD_H -#define HAL_USB_LLD_H - -#if HAL_USE_USB || defined(__DOXYGEN__) - -#include "stm32_usb.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Maximum endpoint address. - */ -#define USB_MAX_ENDPOINTS USB_ENDOPOINTS_NUMBER - -/** - * @brief Status stage handling method. - */ -#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW - -/** - * @brief This device requires the address change after the status packet. - */ -#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS - -/** - * @brief Method for set address acknowledge. - */ -#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief USB1 driver enable switch. - * @details If set to @p TRUE the support for USB1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_USB_USE_USB1) || defined(__DOXYGEN__) -#define STM32_USB_USE_USB1 FALSE -#endif - -/** - * @brief Enables the USB device low power mode on suspend. - */ -#if !defined(STM32_USB_LOW_POWER_ON_SUSPEND) || defined(__DOXYGEN__) -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#endif - -/** - * @brief USB1 interrupt priority level setting. - */ -#if (!defined(STM32_USB_USB1_HP_IRQ_PRIORITY) && \ - (STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER)) || defined(__DOXYGEN__) -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#endif - -/** - * @brief USB1 interrupt priority level setting. - */ -#if !defined(STM32_USB_USB1_LP_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 -#endif - -/** - * @brief Enables isochronous support. - * @note Isochronous support requires special handling and this makes the - * code size increase significantly. - */ -#if !defined(STM32_USB_USE_ISOCHRONOUS) || defined(__DOXYGEN__) -#define STM32_USB_USE_ISOCHRONOUS FALSE -#endif - -/** - * @brief Use faster copy for packets. - * @note Makes the driver larger. - */ -#if !defined(STM32_USB_USE_FAST_COPY) || defined(__DOXYGEN__) -#define STM32_USB_USE_FAST_COPY FALSE -#endif - -/** - * @brief Host wake-up procedure duration. - */ -#if !defined(STM32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__) -#define STM32_USB_HOST_WAKEUP_DURATION 2 -#endif - -/** - * @brief Allowed deviation for the 48MHz clock. - */ -#if !defined(STM32_USB_48MHZ_DELTA) || defined(__DOXYGEN__) -#define STM32_USB_48MHZ_DELTA 0 -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_USB_USE_USB1 && !STM32_HAS_USB -#error "USB not present in the selected device" -#endif - -#if !STM32_USB_USE_USB1 -#error "USB driver activated but no USB peripheral assigned" -#endif - -#if STM32_USB_USE_USB1 && \ - (STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_USB1_HP_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USB HP" -#endif - -#if STM32_USB_USE_USB1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_USB1_LP_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USB LP" -#endif - -#if !defined(STM32_USB1_HP_HANDLER) -#error "STM32_USB1_HP_HANDLER not defined" -#endif - -#if !defined(STM32_USB1_HP_NUMBER) -#error "STM32_USB1_HP_NUMBER not defined" -#endif - -#if !defined(STM32_USB1_LP_HANDLER) -#error "STM32_USB1_LP_HANDLER not defined" -#endif - -#if !defined(STM32_USB1_LP_NUMBER) -#error "STM32_USB1_LP_NUMBER not defined" -#endif - -#if (STM32_USB_HOST_WAKEUP_DURATION < 2) || (STM32_USB_HOST_WAKEUP_DURATION > 15) -#error "invalid STM32_USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15" -#endif - -#if (STM32_USB_48MHZ_DELTA < 0) || (STM32_USB_48MHZ_DELTA > 250000) -#error "invalid STM32_USB_48MHZ_DELTA setting, it must not exceed 250000" -#endif - -#if (STM32_USBCLK < (48000000 - STM32_USB_48MHZ_DELTA)) || \ - (STM32_USBCLK > (48000000 + STM32_USB_48MHZ_DELTA)) -#error "the USB driver requires a 48MHz clock" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an IN endpoint state structure. - */ -typedef struct { - /** - * @brief Requested transmit transfer size. - */ - size_t txsize; - /** - * @brief Transmitted bytes so far. - */ - size_t txcnt; - /** - * @brief Pointer to the transmission linear buffer. - */ - const uint8_t *txbuf; -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Size of the last transmitted packet. - */ - size_t txlast; -} USBInEndpointState; - -/** - * @brief Type of an OUT endpoint state structure. - */ -typedef struct { - /** - * @brief Requested receive transfer size. - */ - size_t rxsize; - /** - * @brief Received bytes so far. - */ - size_t rxcnt; - /** - * @brief Pointer to the receive linear buffer. - */ - uint8_t *rxbuf; -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Number of packets to receive. - */ - uint16_t rxpkts; -} USBOutEndpointState; - -/** - * @brief Type of an USB endpoint configuration structure. - * @note Platform specific restrictions may apply to endpoints. - */ -typedef struct { - /** - * @brief Type and mode of the endpoint. - */ - uint32_t ep_mode; - /** - * @brief Setup packet notification callback. - * @details This callback is invoked when a setup packet has been - * received. - * @post The application must immediately call @p usbReadPacket() in - * order to access the received packet. - * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL - * endpoints, it should be set to @p NULL for other endpoint - * types. - */ - usbepcallback_t setup_cb; - /** - * @brief IN endpoint notification callback. - * @details This field must be set to @p NULL if callback is not required. - */ - usbepcallback_t in_cb; - /** - * @brief OUT endpoint notification callback. - * @details This field must be set to @p NULL if callback is not required. - */ - usbepcallback_t out_cb; - /** - * @brief IN endpoint maximum packet size. - * @details This field must be set to zero if the IN endpoint is not used. - */ - uint16_t in_maxsize; - /** - * @brief OUT endpoint maximum packet size. - * @details This field must be set to zero if the OUT endpoint is not used. - */ - uint16_t out_maxsize; - /** - * @brief @p USBEndpointState associated to the IN endpoint. - * @details This field must be set to @p NULL if the IN endpoint is not - * used. - */ - USBInEndpointState *in_state; - /** - * @brief @p USBEndpointState associated to the OUT endpoint. - * @details This field must be set to @p NULL if the OUT endpoint is not - * used. - */ - USBOutEndpointState *out_state; - /* End of the mandatory fields.*/ - /** - * @brief Reserved field, not currently used. - * @note Initialize this field to 1 in order to be forward compatible. - */ - uint16_t ep_buffers; - /** - * @brief Pointer to a buffer for setup packets. - * @details Setup packets require a dedicated 8-bytes buffer, set this - * field to @p NULL for non-control endpoints. - */ - uint8_t *setup_buf; -} USBEndpointConfig; - -/** - * @brief Type of an USB driver configuration structure. - */ -typedef struct { - /** - * @brief USB events callback. - * @details This callback is invoked when an USB driver event is registered. - */ - usbeventcb_t event_cb; - /** - * @brief Device GET_DESCRIPTOR request callback. - * @note This callback is mandatory and cannot be set to @p NULL. - */ - usbgetdescriptor_t get_descriptor_cb; - /** - * @brief Requests hook callback. - * @details This hook allows to be notified of standard requests or to - * handle non standard requests. - */ - usbreqhandler_t requests_hook_cb; - /** - * @brief Start Of Frame callback. - */ - usbcallback_t sof_cb; - /* End of the mandatory fields.*/ -} USBConfig; - -/** - * @brief Structure representing an USB driver. - */ -struct USBDriver { - /** - * @brief Driver state. - */ - usbstate_t state; - /** - * @brief Current configuration data. - */ - const USBConfig *config; - /** - * @brief Bit map of the transmitting IN endpoints. - */ - uint16_t transmitting; - /** - * @brief Bit map of the receiving OUT endpoints. - */ - uint16_t receiving; - /** - * @brief Active endpoints configurations. - */ - const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an IN endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *in_params[USB_MAX_ENDPOINTS]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an OUT endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *out_params[USB_MAX_ENDPOINTS]; - /** - * @brief Endpoint 0 state. - */ - usbep0state_t ep0state; - /** - * @brief Next position in the buffer to be transferred through endpoint 0. - */ - uint8_t *ep0next; - /** - * @brief Number of bytes yet to be transferred through endpoint 0. - */ - size_t ep0n; - /** - * @brief Endpoint 0 end transaction callback. - */ - usbcallback_t ep0endcb; - /** - * @brief Setup packet buffer. - */ - uint8_t setup[8]; - /** - * @brief Current USB device status. - */ - uint16_t status; - /** - * @brief Assigned USB address. - */ - uint8_t address; - /** - * @brief Current USB device configuration. - */ - uint8_t configuration; - /** - * @brief State of the driver when a suspend happened. - */ - usbstate_t saved_state; -#if defined(USB_DRIVER_EXT_FIELDS) - USB_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the next address in the packet memory. - */ - uint32_t pmnext; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the current frame number. - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The current frame number. - * - * @notapi - */ -#define usb_lld_get_frame_number(usbp) (STM32_USB->FNR & FNR_FN_MASK) - -/** - * @brief Returns the exact size of a receive transaction. - * @details The received size can be different from the size specified in - * @p usbStartReceiveI() because the last packet could have a size - * different from the expected one. - * @pre The OUT endpoint must have been configured in transaction mode - * in order to use this function. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return Received data size. - * - * @notapi - */ -#define usb_lld_get_transaction_size(usbp, ep) \ - ((usbp)->epc[ep]->out_state->rxcnt) - -#if STM32_USB_HAS_BCDR || defined(__DOXYGEN__) -/** - * @brief Connects the USB device. - * - * @notapi - */ -#if !defined(usb_lld_connect_bus) -#define usb_lld_connect_bus(usbp) (STM32_USB->BCDR |= USB_BCDR_DPPU) -#endif - -/** - * @brief Disconnect the USB device. - * - * @notapi - */ -#if !defined(usb_lld_disconnect_bus) -#define usb_lld_disconnect_bus(usbp) (STM32_USB->BCDR &= ~USB_BCDR_DPPU) -#endif -#endif /* STM32_USB_HAS_BCDR */ - -#if defined(STM32L1XX) -#if !defined(usb_lld_connect_bus) -#define usb_lld_connect_bus(usbp) (SYSCFG->PMC |= SYSCFG_PMC_USB_PU) -#endif - -#if !defined(usb_lld_disconnect_bus) -#define usb_lld_disconnect_bus(usbp) (SYSCFG->PMC &= ~SYSCFG_PMC_USB_PU) -#endif -#endif /* STM32L1XX */ - -/** - * @brief Start of host wake-up procedure. - * - * @notapi - */ -#define usb_lld_wakeup_host(usbp) \ - do { \ - STM32_USB->CNTR |= USB_CNTR_RESUME; \ - osalThreadSleepMilliseconds(STM32_USB_HOST_WAKEUP_DURATION); \ - STM32_USB->CNTR &= ~USB_CNTR_RESUME; \ - } while (false) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_USB_USE_USB1 && !defined(__DOXYGEN__) -extern USBDriver USBD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void usb_lld_init(void); - void usb_lld_start(USBDriver *usbp); - void usb_lld_stop(USBDriver *usbp); - void usb_lld_reset(USBDriver *usbp); - void usb_lld_set_address(USBDriver *usbp); - void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); - void usb_lld_disable_endpoints(USBDriver *usbp); - usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); - usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); - void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); - void usb_lld_start_out(USBDriver *usbp, usbep_t ep); - void usb_lld_start_in(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_USB */ - -#endif /* HAL_USB_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USBv1/hal_usb_lld.h + * @brief STM32 USB subsystem low level driver header. + * + * @addtogroup USB + * @{ + */ + +#ifndef HAL_USB_LLD_H +#define HAL_USB_LLD_H + +#if HAL_USE_USB || defined(__DOXYGEN__) + +#include "stm32_usb.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum endpoint address. + */ +#define USB_MAX_ENDPOINTS USB_ENDOPOINTS_NUMBER + +/** + * @brief Status stage handling method. + */ +#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW + +/** + * @brief This device requires the address change after the status packet. + */ +#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS + +/** + * @brief Method for set address acknowledge. + */ +#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief USB1 driver enable switch. + * @details If set to @p TRUE the support for USB1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_USB_USE_USB1) || defined(__DOXYGEN__) +#define STM32_USB_USE_USB1 FALSE +#endif + +/** + * @brief Enables the USB device low power mode on suspend. + */ +#if !defined(STM32_USB_LOW_POWER_ON_SUSPEND) || defined(__DOXYGEN__) +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#endif + +/** + * @brief USB1 interrupt priority level setting. + */ +#if (!defined(STM32_USB_USB1_HP_IRQ_PRIORITY) && \ + (STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER)) || defined(__DOXYGEN__) +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#endif + +/** + * @brief USB1 interrupt priority level setting. + */ +#if !defined(STM32_USB_USB1_LP_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 +#endif + +/** + * @brief Enables isochronous support. + * @note Isochronous support requires special handling and this makes the + * code size increase significantly. + */ +#if !defined(STM32_USB_USE_ISOCHRONOUS) || defined(__DOXYGEN__) +#define STM32_USB_USE_ISOCHRONOUS FALSE +#endif + +/** + * @brief Use faster copy for packets. + * @note Makes the driver larger. + */ +#if !defined(STM32_USB_USE_FAST_COPY) || defined(__DOXYGEN__) +#define STM32_USB_USE_FAST_COPY FALSE +#endif + +/** + * @brief Host wake-up procedure duration. + */ +#if !defined(STM32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__) +#define STM32_USB_HOST_WAKEUP_DURATION 2 +#endif + +/** + * @brief Allowed deviation for the 48MHz clock. + */ +#if !defined(STM32_USB_48MHZ_DELTA) || defined(__DOXYGEN__) +#define STM32_USB_48MHZ_DELTA 0 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_USB_USE_USB1 && !STM32_HAS_USB +#error "USB not present in the selected device" +#endif + +#if !STM32_USB_USE_USB1 +#error "USB driver activated but no USB peripheral assigned" +#endif + +#if STM32_USB_USE_USB1 && \ + (STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_USB1_HP_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USB HP" +#endif + +#if STM32_USB_USE_USB1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_USB1_LP_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USB LP" +#endif + +#if !defined(STM32_USB1_HP_HANDLER) +#error "STM32_USB1_HP_HANDLER not defined" +#endif + +#if !defined(STM32_USB1_HP_NUMBER) +#error "STM32_USB1_HP_NUMBER not defined" +#endif + +#if !defined(STM32_USB1_LP_HANDLER) +#error "STM32_USB1_LP_HANDLER not defined" +#endif + +#if !defined(STM32_USB1_LP_NUMBER) +#error "STM32_USB1_LP_NUMBER not defined" +#endif + +#if (STM32_USB_HOST_WAKEUP_DURATION < 2) || (STM32_USB_HOST_WAKEUP_DURATION > 15) +#error "invalid STM32_USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15" +#endif + +#if (STM32_USB_48MHZ_DELTA < 0) || (STM32_USB_48MHZ_DELTA > 250000) +#error "invalid STM32_USB_48MHZ_DELTA setting, it must not exceed 250000" +#endif + +#if (STM32_USBCLK < (48000000 - STM32_USB_48MHZ_DELTA)) || \ + (STM32_USBCLK > (48000000 + STM32_USB_48MHZ_DELTA)) +#error "the USB driver requires a 48MHz clock" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an IN endpoint state structure. + */ +typedef struct { + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; + /** + * @brief Pointer to the transmission linear buffer. + */ + const uint8_t *txbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Size of the last transmitted packet. + */ + size_t txlast; +} USBInEndpointState; + +/** + * @brief Type of an OUT endpoint state structure. + */ +typedef struct { + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; + /** + * @brief Pointer to the receive linear buffer. + */ + uint8_t *rxbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Number of packets to receive. + */ + uint16_t rxpkts; +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if callback is not required. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if callback is not required. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ + /** + * @brief Reserved field, not currently used. + * @note Initialize this field to 1 in order to be forward compatible. + */ + uint16_t ep_buffers; + /** + * @brief Pointer to a buffer for setup packets. + * @details Setup packets require a dedicated 8-bytes buffer, set this + * field to @p NULL for non-control endpoints. + */ + uint8_t *setup_buf; +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an IN endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *in_params[USB_MAX_ENDPOINTS]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an OUT endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *out_params[USB_MAX_ENDPOINTS]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; + /** + * @brief State of the driver when a suspend happened. + */ + usbstate_t saved_state; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the next address in the packet memory. + */ + uint32_t pmnext; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the current frame number. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The current frame number. + * + * @notapi + */ +#define usb_lld_get_frame_number(usbp) (STM32_USB->FNR & FNR_FN_MASK) + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +#if STM32_USB_HAS_BCDR || defined(__DOXYGEN__) +/** + * @brief Connects the USB device. + * + * @notapi + */ +#if !defined(usb_lld_connect_bus) +#define usb_lld_connect_bus(usbp) (STM32_USB->BCDR |= USB_BCDR_DPPU) +#endif + +/** + * @brief Disconnect the USB device. + * + * @notapi + */ +#if !defined(usb_lld_disconnect_bus) +#define usb_lld_disconnect_bus(usbp) (STM32_USB->BCDR &= ~USB_BCDR_DPPU) +#endif +#endif /* STM32_USB_HAS_BCDR */ + +#if defined(STM32L1XX) +#if !defined(usb_lld_connect_bus) +#define usb_lld_connect_bus(usbp) (SYSCFG->PMC |= SYSCFG_PMC_USB_PU) +#endif + +#if !defined(usb_lld_disconnect_bus) +#define usb_lld_disconnect_bus(usbp) (SYSCFG->PMC &= ~SYSCFG_PMC_USB_PU) +#endif +#endif /* STM32L1XX */ + +/** + * @brief Start of host wake-up procedure. + * + * @notapi + */ +#define usb_lld_wakeup_host(usbp) \ + do { \ + STM32_USB->CNTR |= USB_CNTR_RESUME; \ + osalThreadSleepMilliseconds(STM32_USB_HOST_WAKEUP_DURATION); \ + STM32_USB->CNTR &= ~USB_CNTR_RESUME; \ + } while (false) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_USB_USE_USB1 && !defined(__DOXYGEN__) +extern USBDriver USBD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB */ + +#endif /* HAL_USB_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h b/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h index 9a8595eadf..bd9be355cf 100644 --- a/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h +++ b/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h @@ -1,266 +1,266 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file USBv1/stm32_usb.h - * @brief STM32 USB registers layout header. - * @note This file requires definitions from the ST STM32 header files - * stm32f10x.h or stm32l1xx.h. - * - * @addtogroup USB - * @{ - */ - -#ifndef STM32_USB_H -#define STM32_USB_H - -/** - * @brief Number of the available endpoints. - * @details This value does not include the endpoint 0 which is always present. - */ -#define USB_ENDOPOINTS_NUMBER 7 - -/** - * @brief Width of USB packet memory accesses. - */ -#if STM32_USB_ACCESS_SCHEME_2x16 -typedef uint16_t stm32_usb_pma_t; -#else -typedef uint32_t stm32_usb_pma_t; -#endif - -/** - * @brief USB registers block. - */ -typedef struct { - /** - * @brief Endpoint registers. - */ - volatile uint32_t EPR[USB_ENDOPOINTS_NUMBER + 1]; - /* - * @brief Reserved space. - */ - volatile uint32_t _r20[8]; - /* - * @brief Control Register. - */ - volatile uint32_t CNTR; - /* - * @brief Interrupt Status Register. - */ - volatile uint32_t ISTR; - /* - * @brief Frame Number Register. - */ - volatile uint32_t FNR; - /* - * @brief Device Address Register. - */ - volatile uint32_t DADDR; - /* - * @brief Buffer Table Address. - */ - volatile uint32_t BTABLE; - /* - * @brief LPM Control and Status Register. - */ - volatile uint32_t LPMCSR; -#if STM32_USB_HAS_BCDR - /* - * @brief Battery Charging Detector - */ - volatile uint32_t BCDR; -#endif -} stm32_usb_t; - -/** - * @brief USB descriptor registers block. - */ -typedef struct { - /** - * @brief TX buffer offset register. - */ - volatile stm32_usb_pma_t TXADDR0; - /** - * @brief TX counter register 0. - */ - volatile stm32_usb_pma_t TXCOUNT0; - /** - * @brief RX buffer offset register. - */ - volatile stm32_usb_pma_t RXADDR0; - /** - * @brief RX counter register 0. - */ - volatile stm32_usb_pma_t RXCOUNT0; -} stm32_usb_descriptor_t; - -/** - * @name Register aliases - * @{ - */ -#define RXCOUNT1 TXCOUNT0 -#define TXCOUNT1 RXCOUNT0 -#define RXADDR1 TXADDR0 -#define TXADDR1 RXADDR0 -/** @} */ - -/** - * @brief USB registers block numeric address. - */ -#if defined(USB_BASE) || defined(__DOXYGEN__) -#define STM32_USB_BASE USB_BASE -#else -#define STM32_USB_BASE (APB1PERIPH_BASE + 0x5C00) -#endif - -/** - * @brief USB RAM numeric address. - */ -#if defined(USB_PMAADDR) || defined(__DOXYGEN__) -#define STM32_USBRAM_BASE USB_PMAADDR -#else -#define STM32_USBRAM_BASE (APB1PERIPH_BASE + 0x6000) -#endif - -/** - * @brief Pointer to the USB registers block. - */ -#define STM32_USB ((stm32_usb_t *)STM32_USB_BASE) - -/** - * @brief Pointer to the USB RAM. - */ -#define STM32_USBRAM ((stm32_usb_pma_t *)STM32_USBRAM_BASE) - -/** - * @brief Mask of all the toggling bits in the EPR register. - */ -#define EPR_TOGGLE_MASK (EPR_STAT_TX_MASK | EPR_DTOG_TX | \ - EPR_STAT_RX_MASK | EPR_DTOG_RX | \ - EPR_SETUP) - -#define EPR_EA_MASK 0x000F -#define EPR_STAT_TX_MASK 0x0030 -#define EPR_STAT_TX_DIS 0x0000 -#define EPR_STAT_TX_STALL 0x0010 -#define EPR_STAT_TX_NAK 0x0020 -#define EPR_STAT_TX_VALID 0x0030 -#define EPR_DTOG_TX 0x0040 -#define EPR_SWBUF_RX EPR_DTOG_TX -#define EPR_CTR_TX 0x0080 -#define EPR_EP_KIND 0x0100 -#define EPR_EP_DBL_BUF EPR_EP_KIND -#define EPR_EP_STATUS_OUT EPR_EP_KIND -#define EPR_EP_TYPE_MASK 0x0600 -#define EPR_EP_TYPE_BULK 0x0000 -#define EPR_EP_TYPE_CONTROL 0x0200 -#define EPR_EP_TYPE_ISO 0x0400 -#define EPR_EP_TYPE_INTERRUPT 0x0600 -#define EPR_SETUP 0x0800 -#define EPR_STAT_RX_MASK 0x3000 -#define EPR_STAT_RX_DIS 0x0000 -#define EPR_STAT_RX_STALL 0x1000 -#define EPR_STAT_RX_NAK 0x2000 -#define EPR_STAT_RX_VALID 0x3000 -#define EPR_DTOG_RX 0x4000 -#define EPR_SWBUF_TX EPR_DTOG_RX -#define EPR_CTR_RX 0x8000 - -#define CNTR_FRES 0x0001 -#define CNTR_PDWN 0x0002 -#define CNTR_LP_MODE 0x0004 -#define CNTR_FSUSP 0x0008 -#define CNTR_RESUME 0x0010 -#define CNTR_ESOFM 0x0100 -#define CNTR_SOFM 0x0200 -#define CNTR_RESETM 0x0400 -#define CNTR_SUSPM 0x0800 -#define CNTR_WKUPM 0x1000 -#define CNTR_ERRM 0x2000 -#define CNTR_PMAOVRM 0x4000 -#define CNTR_CTRM 0x8000 - -#define ISTR_EP_ID_MASK 0x000F -#define ISTR_DIR 0x0010 -#define ISTR_ESOF 0x0100 -#define ISTR_SOF 0x0200 -#define ISTR_RESET 0x0400 -#define ISTR_SUSP 0x0800 -#define ISTR_WKUP 0x1000 -#define ISTR_ERR 0x2000 -#define ISTR_PMAOVR 0x4000 -#define ISTR_CTR 0x8000 - -#define FNR_FN_MASK 0x07FF -#define FNR_LSOF 0x1800 -#define FNR_LCK 0x2000 -#define FNR_RXDM 0x4000 -#define FNR_RXDP 0x8000 - -#define DADDR_ADD_MASK 0x007F -#define DADDR_EF 0x0080 - -#define RXCOUNT_COUNT_MASK 0x03FF -#define TXCOUNT_COUNT_MASK 0x03FF - -#define EPR_CTR_MASK (EPR_CTR_TX | EPR_CTR_RX) - -#define EPR_SET(ep, epr) \ - STM32_USB->EPR[ep] = ((epr) & ~EPR_TOGGLE_MASK) | EPR_CTR_MASK - -#define EPR_TOGGLE(ep, epr) \ - STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] ^ ((epr) & EPR_TOGGLE_MASK)) \ - | EPR_CTR_MASK - -#define EPR_SET_STAT_RX(ep, epr) \ - STM32_USB->EPR[ep] = ((STM32_USB->EPR[ep] & \ - ~(EPR_TOGGLE_MASK & ~EPR_STAT_RX_MASK)) ^ \ - (epr)) | EPR_CTR_MASK - -#define EPR_SET_STAT_TX(ep, epr) \ - STM32_USB->EPR[ep] = ((STM32_USB->EPR[ep] & \ - ~(EPR_TOGGLE_MASK & ~EPR_STAT_TX_MASK)) ^ \ - (epr)) | EPR_CTR_MASK - -#define EPR_CLEAR_CTR_RX(ep) \ - STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & ~EPR_CTR_RX & ~EPR_TOGGLE_MASK)\ - | EPR_CTR_TX - -#define EPR_CLEAR_CTR_TX(ep) \ - STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & ~EPR_CTR_TX & ~EPR_TOGGLE_MASK)\ - | EPR_CTR_RX - -/** - * @brief Returns an endpoint descriptor pointer. - */ -#define USB_GET_DESCRIPTOR(ep) \ - ((stm32_usb_descriptor_t *)((uint32_t)STM32_USBRAM_BASE + \ - (uint32_t)STM32_USB->BTABLE + \ - (uint32_t)(ep) * \ - sizeof(stm32_usb_descriptor_t))) - -/** - * @brief Converts from a PMA address to a physical address. - */ -#define USB_ADDR2PTR(addr) \ - ((stm32_usb_pma_t *)((addr) * \ - (sizeof(stm32_usb_pma_t) / 2) + \ - STM32_USBRAM_BASE)) - -#endif /* STM32_USB_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USBv1/stm32_usb.h + * @brief STM32 USB registers layout header. + * @note This file requires definitions from the ST STM32 header files + * stm32f10x.h or stm32l1xx.h. + * + * @addtogroup USB + * @{ + */ + +#ifndef STM32_USB_H +#define STM32_USB_H + +/** + * @brief Number of the available endpoints. + * @details This value does not include the endpoint 0 which is always present. + */ +#define USB_ENDOPOINTS_NUMBER 7 + +/** + * @brief Width of USB packet memory accesses. + */ +#if STM32_USB_ACCESS_SCHEME_2x16 +typedef uint16_t stm32_usb_pma_t; +#else +typedef uint32_t stm32_usb_pma_t; +#endif + +/** + * @brief USB registers block. + */ +typedef struct { + /** + * @brief Endpoint registers. + */ + volatile uint32_t EPR[USB_ENDOPOINTS_NUMBER + 1]; + /* + * @brief Reserved space. + */ + volatile uint32_t _r20[8]; + /* + * @brief Control Register. + */ + volatile uint32_t CNTR; + /* + * @brief Interrupt Status Register. + */ + volatile uint32_t ISTR; + /* + * @brief Frame Number Register. + */ + volatile uint32_t FNR; + /* + * @brief Device Address Register. + */ + volatile uint32_t DADDR; + /* + * @brief Buffer Table Address. + */ + volatile uint32_t BTABLE; + /* + * @brief LPM Control and Status Register. + */ + volatile uint32_t LPMCSR; +#if STM32_USB_HAS_BCDR + /* + * @brief Battery Charging Detector + */ + volatile uint32_t BCDR; +#endif +} stm32_usb_t; + +/** + * @brief USB descriptor registers block. + */ +typedef struct { + /** + * @brief TX buffer offset register. + */ + volatile stm32_usb_pma_t TXADDR0; + /** + * @brief TX counter register 0. + */ + volatile stm32_usb_pma_t TXCOUNT0; + /** + * @brief RX buffer offset register. + */ + volatile stm32_usb_pma_t RXADDR0; + /** + * @brief RX counter register 0. + */ + volatile stm32_usb_pma_t RXCOUNT0; +} stm32_usb_descriptor_t; + +/** + * @name Register aliases + * @{ + */ +#define RXCOUNT1 TXCOUNT0 +#define TXCOUNT1 RXCOUNT0 +#define RXADDR1 TXADDR0 +#define TXADDR1 RXADDR0 +/** @} */ + +/** + * @brief USB registers block numeric address. + */ +#if defined(USB_BASE) || defined(__DOXYGEN__) +#define STM32_USB_BASE USB_BASE +#else +#define STM32_USB_BASE (APB1PERIPH_BASE + 0x5C00) +#endif + +/** + * @brief USB RAM numeric address. + */ +#if defined(USB_PMAADDR) || defined(__DOXYGEN__) +#define STM32_USBRAM_BASE USB_PMAADDR +#else +#define STM32_USBRAM_BASE (APB1PERIPH_BASE + 0x6000) +#endif + +/** + * @brief Pointer to the USB registers block. + */ +#define STM32_USB ((stm32_usb_t *)STM32_USB_BASE) + +/** + * @brief Pointer to the USB RAM. + */ +#define STM32_USBRAM ((stm32_usb_pma_t *)STM32_USBRAM_BASE) + +/** + * @brief Mask of all the toggling bits in the EPR register. + */ +#define EPR_TOGGLE_MASK (EPR_STAT_TX_MASK | EPR_DTOG_TX | \ + EPR_STAT_RX_MASK | EPR_DTOG_RX | \ + EPR_SETUP) + +#define EPR_EA_MASK 0x000F +#define EPR_STAT_TX_MASK 0x0030 +#define EPR_STAT_TX_DIS 0x0000 +#define EPR_STAT_TX_STALL 0x0010 +#define EPR_STAT_TX_NAK 0x0020 +#define EPR_STAT_TX_VALID 0x0030 +#define EPR_DTOG_TX 0x0040 +#define EPR_SWBUF_RX EPR_DTOG_TX +#define EPR_CTR_TX 0x0080 +#define EPR_EP_KIND 0x0100 +#define EPR_EP_DBL_BUF EPR_EP_KIND +#define EPR_EP_STATUS_OUT EPR_EP_KIND +#define EPR_EP_TYPE_MASK 0x0600 +#define EPR_EP_TYPE_BULK 0x0000 +#define EPR_EP_TYPE_CONTROL 0x0200 +#define EPR_EP_TYPE_ISO 0x0400 +#define EPR_EP_TYPE_INTERRUPT 0x0600 +#define EPR_SETUP 0x0800 +#define EPR_STAT_RX_MASK 0x3000 +#define EPR_STAT_RX_DIS 0x0000 +#define EPR_STAT_RX_STALL 0x1000 +#define EPR_STAT_RX_NAK 0x2000 +#define EPR_STAT_RX_VALID 0x3000 +#define EPR_DTOG_RX 0x4000 +#define EPR_SWBUF_TX EPR_DTOG_RX +#define EPR_CTR_RX 0x8000 + +#define CNTR_FRES 0x0001 +#define CNTR_PDWN 0x0002 +#define CNTR_LP_MODE 0x0004 +#define CNTR_FSUSP 0x0008 +#define CNTR_RESUME 0x0010 +#define CNTR_ESOFM 0x0100 +#define CNTR_SOFM 0x0200 +#define CNTR_RESETM 0x0400 +#define CNTR_SUSPM 0x0800 +#define CNTR_WKUPM 0x1000 +#define CNTR_ERRM 0x2000 +#define CNTR_PMAOVRM 0x4000 +#define CNTR_CTRM 0x8000 + +#define ISTR_EP_ID_MASK 0x000F +#define ISTR_DIR 0x0010 +#define ISTR_ESOF 0x0100 +#define ISTR_SOF 0x0200 +#define ISTR_RESET 0x0400 +#define ISTR_SUSP 0x0800 +#define ISTR_WKUP 0x1000 +#define ISTR_ERR 0x2000 +#define ISTR_PMAOVR 0x4000 +#define ISTR_CTR 0x8000 + +#define FNR_FN_MASK 0x07FF +#define FNR_LSOF 0x1800 +#define FNR_LCK 0x2000 +#define FNR_RXDM 0x4000 +#define FNR_RXDP 0x8000 + +#define DADDR_ADD_MASK 0x007F +#define DADDR_EF 0x0080 + +#define RXCOUNT_COUNT_MASK 0x03FF +#define TXCOUNT_COUNT_MASK 0x03FF + +#define EPR_CTR_MASK (EPR_CTR_TX | EPR_CTR_RX) + +#define EPR_SET(ep, epr) \ + STM32_USB->EPR[ep] = ((epr) & ~EPR_TOGGLE_MASK) | EPR_CTR_MASK + +#define EPR_TOGGLE(ep, epr) \ + STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] ^ ((epr) & EPR_TOGGLE_MASK)) \ + | EPR_CTR_MASK + +#define EPR_SET_STAT_RX(ep, epr) \ + STM32_USB->EPR[ep] = ((STM32_USB->EPR[ep] & \ + ~(EPR_TOGGLE_MASK & ~EPR_STAT_RX_MASK)) ^ \ + (epr)) | EPR_CTR_MASK + +#define EPR_SET_STAT_TX(ep, epr) \ + STM32_USB->EPR[ep] = ((STM32_USB->EPR[ep] & \ + ~(EPR_TOGGLE_MASK & ~EPR_STAT_TX_MASK)) ^ \ + (epr)) | EPR_CTR_MASK + +#define EPR_CLEAR_CTR_RX(ep) \ + STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & ~EPR_CTR_RX & ~EPR_TOGGLE_MASK)\ + | EPR_CTR_TX + +#define EPR_CLEAR_CTR_TX(ep) \ + STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & ~EPR_CTR_TX & ~EPR_TOGGLE_MASK)\ + | EPR_CTR_RX + +/** + * @brief Returns an endpoint descriptor pointer. + */ +#define USB_GET_DESCRIPTOR(ep) \ + ((stm32_usb_descriptor_t *)((uint32_t)STM32_USBRAM_BASE + \ + (uint32_t)STM32_USB->BTABLE + \ + (uint32_t)(ep) * \ + sizeof(stm32_usb_descriptor_t))) + +/** + * @brief Converts from a PMA address to a physical address. + */ +#define USB_ADDR2PTR(addr) \ + ((stm32_usb_pma_t *)((addr) * \ + (sizeof(stm32_usb_pma_t) / 2) + \ + STM32_USBRAM_BASE)) + +#endif /* STM32_USB_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/xWDGv1/driver.mk b/os/hal/ports/STM32/LLD/xWDGv1/driver.mk index a4d8bddaa4..e6314fdff2 100644 --- a/os/hal/ports/STM32/LLD/xWDGv1/driver.mk +++ b/os/hal/ports/STM32/LLD/xWDGv1/driver.mk @@ -1,9 +1,9 @@ -ifeq ($(USE_SMART_BUILD),yes) -ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c -endif - -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1 +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1 diff --git a/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c b/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c index 07c17a1ee0..44bdf14e55 100644 --- a/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c +++ b/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c @@ -1,135 +1,135 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file xWDGv1/hal_wdg_lld.c - * @brief WDG Driver subsystem low level driver source. - * - * @addtogroup WDG - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define KR_KEY_RELOAD 0xAAAAU -#define KR_KEY_ENABLE 0xCCCCU -#define KR_KEY_WRITE 0x5555U -#define KR_KEY_PROTECT 0x0000U - -#if !defined(IWDG) && defined(IWDG1) -#define IWDG IWDG1 -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -#if STM32_WDG_USE_IWDG || defined(__DOXYGEN__) -WDGDriver WDGD1; -#endif - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level WDG driver initialization. - * - * @notapi - */ -void wdg_lld_init(void) { - -#if STM32_WDG_USE_IWDG - WDGD1.state = WDG_STOP; - WDGD1.wdg = IWDG; -#endif -} - -/** - * @brief Configures and activates the WDG peripheral. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * - * @notapi - */ -void wdg_lld_start(WDGDriver *wdgp) { - - /* Enable IWDG and unlock for write.*/ - wdgp->wdg->KR = KR_KEY_ENABLE; - wdgp->wdg->KR = KR_KEY_WRITE; - - /* Write configuration.*/ - wdgp->wdg->PR = wdgp->config->pr; - wdgp->wdg->RLR = wdgp->config->rlr; - - /* Wait the registers to be updated.*/ - while (wdgp->wdg->SR != 0) - ; - -#if STM32_IWDG_IS_WINDOWED - /* This also triggers a refresh.*/ - wdgp->wdg->WINR = wdgp->config->winr; -#else - wdgp->wdg->KR = KR_KEY_RELOAD; -#endif -} - -/** - * @brief Deactivates the WDG peripheral. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * - * @notapi - */ -void wdg_lld_stop(WDGDriver *wdgp) { - - osalDbgAssert(wdgp->state == WDG_STOP, - "IWDG cannot be stopped once activated"); -} - -/** - * @brief Reloads WDG's counter. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * - * @notapi - */ -void wdg_lld_reset(WDGDriver * wdgp) { - - wdgp->wdg->KR = KR_KEY_RELOAD; -} - -#endif /* HAL_USE_WDG == TRUE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file xWDGv1/hal_wdg_lld.c + * @brief WDG Driver subsystem low level driver source. + * + * @addtogroup WDG + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define KR_KEY_RELOAD 0xAAAAU +#define KR_KEY_ENABLE 0xCCCCU +#define KR_KEY_WRITE 0x5555U +#define KR_KEY_PROTECT 0x0000U + +#if !defined(IWDG) && defined(IWDG1) +#define IWDG IWDG1 +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +#if STM32_WDG_USE_IWDG || defined(__DOXYGEN__) +WDGDriver WDGD1; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level WDG driver initialization. + * + * @notapi + */ +void wdg_lld_init(void) { + +#if STM32_WDG_USE_IWDG + WDGD1.state = WDG_STOP; + WDGD1.wdg = IWDG; +#endif +} + +/** + * @brief Configures and activates the WDG peripheral. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * + * @notapi + */ +void wdg_lld_start(WDGDriver *wdgp) { + + /* Enable IWDG and unlock for write.*/ + wdgp->wdg->KR = KR_KEY_ENABLE; + wdgp->wdg->KR = KR_KEY_WRITE; + + /* Write configuration.*/ + wdgp->wdg->PR = wdgp->config->pr; + wdgp->wdg->RLR = wdgp->config->rlr; + + /* Wait the registers to be updated.*/ + while (wdgp->wdg->SR != 0) + ; + +#if STM32_IWDG_IS_WINDOWED + /* This also triggers a refresh.*/ + wdgp->wdg->WINR = wdgp->config->winr; +#else + wdgp->wdg->KR = KR_KEY_RELOAD; +#endif +} + +/** + * @brief Deactivates the WDG peripheral. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * + * @notapi + */ +void wdg_lld_stop(WDGDriver *wdgp) { + + osalDbgAssert(wdgp->state == WDG_STOP, + "IWDG cannot be stopped once activated"); +} + +/** + * @brief Reloads WDG's counter. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * + * @notapi + */ +void wdg_lld_reset(WDGDriver * wdgp) { + + wdgp->wdg->KR = KR_KEY_RELOAD; +} + +#endif /* HAL_USE_WDG == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h b/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h index 752889976e..24979498a5 100644 --- a/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h +++ b/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h @@ -1,183 +1,183 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file xWDGv1/hal_wdg_lld.h - * @brief WDG Driver subsystem low level driver header. - * - * @addtogroup WDG - * @{ - */ - -#ifndef HAL_WDG_LLD_H -#define HAL_WDG_LLD_H - -#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name RLR register definitions - * @{ - */ -#define STM32_IWDG_RL_MASK (0x00000FFF << 0) -#define STM32_IWDG_RL(n) ((n) << 0) -/** @} */ - -/** - * @name PR register definitions - * @{ - */ -#define STM32_IWDG_PR_MASK (7 << 0) -#define STM32_IWDG_PR_4 0U -#define STM32_IWDG_PR_8 1U -#define STM32_IWDG_PR_16 2U -#define STM32_IWDG_PR_32 3U -#define STM32_IWDG_PR_64 4U -#define STM32_IWDG_PR_128 5U -#define STM32_IWDG_PR_256 6U -/** @} */ - -/** - * @name WINR register definitions - * @{ - */ -#define STM32_IWDG_WIN_MASK (0x00000FFF << 0) -#define STM32_IWDG_WIN(n) ((n) << 0) -#define STM32_IWDG_WIN_DISABLED STM32_IWDG_WIN(0x00000FFF) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief IWDG driver enable switch. - * @details If set to @p TRUE the support for IWDG is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_WDG_USE_IWDG) || defined(__DOXYGEN__) -#define STM32_WDG_USE_IWDG FALSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_WDG_USE_IWDG && !STM32_HAS_IWDG -#error "IWDG not present in the selected device" -#endif - -#if !STM32_WDG_USE_IWDG -#error "WDG driver activated but no xWDG peripheral assigned" -#endif - -#if !defined(STM32_LSI_ENABLED) -#error "STM32_LSI_ENABLED not defined" -#endif - -#if (STM32_WDG_USE_IWDG == TRUE) && (STM32_LSI_ENABLED == FALSE) -#error "IWDG requires LSI clock" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an WDG driver. - */ -typedef struct WDGDriver WDGDriver; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Configuration of the IWDG_PR register. - * @details See the STM32 reference manual for details. - */ - uint32_t pr; - /** - * @brief Configuration of the IWDG_RLR register. - * @details See the STM32 reference manual for details. - */ - uint32_t rlr; -#if STM32_IWDG_IS_WINDOWED || defined(__DOXYGEN__) - /** - * @brief Configuration of the IWDG_WINR register. - * @details See the STM32 reference manual for details. - * @note This field is not present in F1, F2, F4, L1 sub-families. - */ - uint32_t winr; -#endif -} WDGConfig; - -/** - * @brief Structure representing an WDG driver. - */ -struct WDGDriver { - /** - * @brief Driver state. - */ - wdgstate_t state; - /** - * @brief Current configuration data. - */ - const WDGConfig *config; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the IWDG registers block. - */ - IWDG_TypeDef *wdg; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_WDG_USE_IWDG && !defined(__DOXYGEN__) -extern WDGDriver WDGD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void wdg_lld_init(void); - void wdg_lld_start(WDGDriver *wdgp); - void wdg_lld_stop(WDGDriver *wdgp); - void wdg_lld_reset(WDGDriver *wdgp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_WDG == TRUE */ - -#endif /* HAL_WDG_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file xWDGv1/hal_wdg_lld.h + * @brief WDG Driver subsystem low level driver header. + * + * @addtogroup WDG + * @{ + */ + +#ifndef HAL_WDG_LLD_H +#define HAL_WDG_LLD_H + +#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name RLR register definitions + * @{ + */ +#define STM32_IWDG_RL_MASK (0x00000FFF << 0) +#define STM32_IWDG_RL(n) ((n) << 0) +/** @} */ + +/** + * @name PR register definitions + * @{ + */ +#define STM32_IWDG_PR_MASK (7 << 0) +#define STM32_IWDG_PR_4 0U +#define STM32_IWDG_PR_8 1U +#define STM32_IWDG_PR_16 2U +#define STM32_IWDG_PR_32 3U +#define STM32_IWDG_PR_64 4U +#define STM32_IWDG_PR_128 5U +#define STM32_IWDG_PR_256 6U +/** @} */ + +/** + * @name WINR register definitions + * @{ + */ +#define STM32_IWDG_WIN_MASK (0x00000FFF << 0) +#define STM32_IWDG_WIN(n) ((n) << 0) +#define STM32_IWDG_WIN_DISABLED STM32_IWDG_WIN(0x00000FFF) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief IWDG driver enable switch. + * @details If set to @p TRUE the support for IWDG is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_WDG_USE_IWDG) || defined(__DOXYGEN__) +#define STM32_WDG_USE_IWDG FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_WDG_USE_IWDG && !STM32_HAS_IWDG +#error "IWDG not present in the selected device" +#endif + +#if !STM32_WDG_USE_IWDG +#error "WDG driver activated but no xWDG peripheral assigned" +#endif + +#if !defined(STM32_LSI_ENABLED) +#error "STM32_LSI_ENABLED not defined" +#endif + +#if (STM32_WDG_USE_IWDG == TRUE) && (STM32_LSI_ENABLED == FALSE) +#error "IWDG requires LSI clock" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an WDG driver. + */ +typedef struct WDGDriver WDGDriver; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Configuration of the IWDG_PR register. + * @details See the STM32 reference manual for details. + */ + uint32_t pr; + /** + * @brief Configuration of the IWDG_RLR register. + * @details See the STM32 reference manual for details. + */ + uint32_t rlr; +#if STM32_IWDG_IS_WINDOWED || defined(__DOXYGEN__) + /** + * @brief Configuration of the IWDG_WINR register. + * @details See the STM32 reference manual for details. + * @note This field is not present in F1, F2, F4, L1 sub-families. + */ + uint32_t winr; +#endif +} WDGConfig; + +/** + * @brief Structure representing an WDG driver. + */ +struct WDGDriver { + /** + * @brief Driver state. + */ + wdgstate_t state; + /** + * @brief Current configuration data. + */ + const WDGConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the IWDG registers block. + */ + IWDG_TypeDef *wdg; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_WDG_USE_IWDG && !defined(__DOXYGEN__) +extern WDGDriver WDGD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void wdg_lld_init(void); + void wdg_lld_start(WDGDriver *wdgp); + void wdg_lld_stop(WDGDriver *wdgp); + void wdg_lld_reset(WDGDriver *wdgp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_WDG == TRUE */ + +#endif /* HAL_WDG_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F0xx/hal_lld.c b/os/hal/ports/STM32/STM32F0xx/hal_lld.c index 2815d5f611..cc81125119 100644 --- a/os/hal/ports/STM32/STM32F0xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32F0xx/hal_lld.c @@ -1,363 +1,364 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/hal_lld.c - * @brief STM32F0xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define STM32_PLLXTPRE_OFFSET 17 /**< PLLXTPRE offset */ -#define STM32_PLLXTPRE_MASK 0x01 /**< PLLXTPRE mask */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f0xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) -#if defined(STM32_DMA1_CH23_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 streams 2 and 3 shared ISR. - * @note It is declared here because this device has a non-standard - * DMA shared IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH23_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 2.*/ - dmaServeInterrupt(STM32_DMA1_STREAM2); - - /* Check on channel 3.*/ - dmaServeInterrupt(STM32_DMA1_STREAM3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* defined(STM32_DMA1_CH23_HANDLER) */ - -#if defined(STM32_DMA1_CH4567_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 streams 4, 5, 6 and 7 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA1_CH4567_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 4.*/ - dmaServeInterrupt(STM32_DMA1_STREAM4); - - /* Check on channel 5.*/ - dmaServeInterrupt(STM32_DMA1_STREAM5); - -#if STM32_DMA1_NUM_CHANNELS > 5 - /* Check on channel 6.*/ - dmaServeInterrupt(STM32_DMA1_STREAM6); -#endif - -#if STM32_DMA1_NUM_CHANNELS > 6 - /* Check on channel 7.*/ - dmaServeInterrupt(STM32_DMA1_STREAM7); -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif /* defined(STM32_DMA1_CH4567_HANDLER) */ - -#if defined(STM32_DMA12_CH23_CH12_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 streams 2 and 3, DMA2 streams 1 and 1 shared ISR. - * @note It is declared here because this device has a non-standard - * DMA shared IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA12_CH23_CH12_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 2 of DMA1.*/ - dmaServeInterrupt(STM32_DMA1_STREAM2); - - /* Check on channel 3 of DMA1.*/ - dmaServeInterrupt(STM32_DMA1_STREAM3); - - /* Check on channel 1 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM1); - - /* Check on channel 2 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* defined(STM32_DMA12_CH23_CH12_HANDLER) */ - -#if defined(STM32_DMA12_CH4567_CH345_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA1 streams 4, 5, 6 and 7, DMA2 streams 3, 4 and 5 shared ISR. - * @note It is declared here because this device has a non-standard - * DMA shared IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA12_CH4567_CH345_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 4 of DMA1.*/ - dmaServeInterrupt(STM32_DMA1_STREAM4); - - /* Check on channel 5 of DMA1.*/ - dmaServeInterrupt(STM32_DMA1_STREAM5); - - /* Check on channel 6 of DMA1.*/ - dmaServeInterrupt(STM32_DMA1_STREAM6); - - /* Check on channel 7 of DMA1.*/ - dmaServeInterrupt(STM32_DMA1_STREAM7); - - /* Check on channel 3 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM3); - - /* Check on channel 4 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM4); - - /* Check on channel 5 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* defined(STM32_DMA12_CH4567_CH345_HANDLER) */ -#endif /* defined(STM32_DMA_REQUIRED) */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB(~STM32_GPIO_EN_MASK); - rccResetAPB1(0xFFFFFFFF); - rccResetAPB2(~RCC_APB2RSTR_DBGMCURST); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32 clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. Clearing the register has to be postponed after HSI is the - new source.*/ - RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers finally cleared to reset values.*/ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_HSI14_ENABLED - /* HSI14 activation.*/ - RCC->CR2 |= RCC_CR2_HSI14ON; - while (!(RCC->CR2 & RCC_CR2_HSI14RDY)) - ; /* Waits until HSI14 is stable. */ -#endif - -#if STM32_HSI48_ENABLED - /* HSI48 activation.*/ - RCC->CR2 |= RCC_CR2_HSI48ON; - while (!(RCC->CR2 & RCC_CR2_HSI48RDY)) - ; /* Waits until HSI48 is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - - /* Clock settings.*/ - /* CFGR2 must be configured first since CFGR value could change CFGR2 */ - RCC->CFGR2 = STM32_PREDIV; - RCC->CFGR = STM32_PLLNODIV | STM32_MCOPRE | STM32_MCOSEL | STM32_PLLMUL | - STM32_PLLSRC | STM32_PPRE | STM32_HPRE | - ((STM32_PREDIV & STM32_PLLXTPRE_MASK) << STM32_PLLXTPRE_OFFSET); -#if STM32_CECSW == STM32_CECSW_OFF - RCC->CFGR3 = STM32_USBSW | STM32_I2C1SW | STM32_USART1SW; -#else - RCC->CFGR3 = STM32_USBSW | STM32_CECSW | STM32_I2C1SW | STM32_USART1SW; -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - /* Switches clock source.*/ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; /* Waits selection complete. */ -#endif - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -#endif /* !STM32_NO_INIT */ -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/hal_lld.c + * @brief STM32F0xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define STM32_PLLXTPRE_OFFSET 17 /**< PLLXTPRE offset */ +#define STM32_PLLXTPRE_MASK 0x01 /**< PLLXTPRE mask */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f0xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) +#if defined(STM32_DMA1_CH23_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 streams 2 and 3 shared ISR. + * @note It is declared here because this device has a non-standard + * DMA shared IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH23_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 2.*/ + dmaServeInterrupt(STM32_DMA1_STREAM2); + + /* Check on channel 3.*/ + dmaServeInterrupt(STM32_DMA1_STREAM3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* defined(STM32_DMA1_CH23_HANDLER) */ + +#if defined(STM32_DMA1_CH4567_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 streams 4, 5, 6 and 7 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA1_CH4567_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 4.*/ + dmaServeInterrupt(STM32_DMA1_STREAM4); + + /* Check on channel 5.*/ + dmaServeInterrupt(STM32_DMA1_STREAM5); + +#if STM32_DMA1_NUM_CHANNELS > 5 + /* Check on channel 6.*/ + dmaServeInterrupt(STM32_DMA1_STREAM6); +#endif + +#if STM32_DMA1_NUM_CHANNELS > 6 + /* Check on channel 7.*/ + dmaServeInterrupt(STM32_DMA1_STREAM7); +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif /* defined(STM32_DMA1_CH4567_HANDLER) */ + +#if defined(STM32_DMA12_CH23_CH12_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 streams 2 and 3, DMA2 streams 1 and 1 shared ISR. + * @note It is declared here because this device has a non-standard + * DMA shared IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA12_CH23_CH12_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 2 of DMA1.*/ + dmaServeInterrupt(STM32_DMA1_STREAM2); + + /* Check on channel 3 of DMA1.*/ + dmaServeInterrupt(STM32_DMA1_STREAM3); + + /* Check on channel 1 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM1); + + /* Check on channel 2 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* defined(STM32_DMA12_CH23_CH12_HANDLER) */ + +#if defined(STM32_DMA12_CH4567_CH345_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA1 streams 4, 5, 6 and 7, DMA2 streams 3, 4 and 5 shared ISR. + * @note It is declared here because this device has a non-standard + * DMA shared IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA12_CH4567_CH345_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 4 of DMA1.*/ + dmaServeInterrupt(STM32_DMA1_STREAM4); + + /* Check on channel 5 of DMA1.*/ + dmaServeInterrupt(STM32_DMA1_STREAM5); + + /* Check on channel 6 of DMA1.*/ + dmaServeInterrupt(STM32_DMA1_STREAM6); + + /* Check on channel 7 of DMA1.*/ + dmaServeInterrupt(STM32_DMA1_STREAM7); + + /* Check on channel 3 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM3); + + /* Check on channel 4 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM4); + + /* Check on channel 5 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* defined(STM32_DMA12_CH4567_CH345_HANDLER) */ +#endif /* defined(STM32_DMA_REQUIRED) */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB(~STM32_GPIO_EN_MASK); + rccResetAPB1(0xFFFFFFFF); + rccResetAPB2(~RCC_APB2RSTR_DBGMCURST); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. Clearing the register has to be postponed after HSI is the + new source.*/ + RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers finally cleared to reset values.*/ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_HSI14_ENABLED + /* HSI14 activation.*/ + RCC->CR2 |= RCC_CR2_HSI14ON; + while (!(RCC->CR2 & RCC_CR2_HSI14RDY)) + ; /* Waits until HSI14 is stable. */ +#endif + +#if STM32_HSI48_ENABLED + /* HSI48 activation.*/ + RCC->CR2 |= RCC_CR2_HSI48ON; + while (!(RCC->CR2 & RCC_CR2_HSI48RDY)) + ; /* Waits until HSI48 is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + + /* Clock settings.*/ + /* CFGR2 must be configured first since CFGR value could change CFGR2 */ + RCC->CFGR2 = STM32_PREDIV; + RCC->CFGR = STM32_PLLNODIV | STM32_MCOPRE | STM32_MCOSEL | STM32_PLLMUL | + STM32_PLLSRC | STM32_PPRE | STM32_HPRE | + ((STM32_PREDIV & STM32_PLLXTPRE_MASK) << STM32_PLLXTPRE_OFFSET); +#if STM32_CECSW == STM32_CECSW_OFF + RCC->CFGR3 = STM32_USBSW | STM32_I2C1SW | STM32_USART1SW; +#else + RCC->CFGR3 = STM32_USBSW | STM32_CECSW | STM32_I2C1SW | STM32_USART1SW; +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + /* Switches clock source.*/ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; /* Waits selection complete. */ +#endif + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +#endif /* !STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F0xx/hal_lld.h b/os/hal/ports/STM32/STM32F0xx/hal_lld.h index 82e3e1db8f..df7ff7fe7b 100644 --- a/os/hal/ports/STM32/STM32F0xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32F0xx/hal_lld.h @@ -1,1025 +1,1033 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/hal_lld.h - * @brief STM32F0xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32F030x4, STM32F030x6, STM32F030x8, STM32F030xC, - * STM32F070x6, STM32F070xB for Value Line devices. - * - STM32F031x6, STM32F051x8, STM32F071xB, STM32F091xC - * for Access Line devices. - * - STM32F042x6, STM32F072xB for USB Line devices. - * - STM32F038xx, STM32F048xx, STM32F058xx, STM32F078xx, - * STM32F098xx for Low Voltage Line devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -/* - * Registry definitions. - */ -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32F030x4) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F030x4 Entry Level Value Line devices" - -#elif defined(STM32F030x6) -#define PLATFORM_NAME "STM32F030x6 Entry Level Value Line devices" - -#elif defined(STM32F030x8) -#define PLATFORM_NAME "STM32F030x8 Entry Level Value Line devices" - -#elif defined(STM32F030xC) -#define PLATFORM_NAME "STM32F030xC Entry Level Value Line devices" - -#elif defined(STM32F070x6) -#define PLATFORM_NAME "STM32F070x6 Entry Level Value Line devices" - -#elif defined(STM32F070xB) -#define PLATFORM_NAME "STM32F070xB Entry Level Value Line devices" - -#elif defined(STM32F031x6) -#define PLATFORM_NAME "STM32F031x6 Entry Level Access Line devices" - -#elif defined(STM32F051x8) -#define PLATFORM_NAME "STM32F051x8 Entry Level Access Line devices" - -#elif defined(STM32F071xB) -#define PLATFORM_NAME "STM32F071xB Entry Level Access Line devices" - -#elif defined(STM32F091xC) -#define PLATFORM_NAME "STM32F091xC Entry Level Access Line devices" - -#elif defined(STM32F042x6) -#define PLATFORM_NAME "STM32F042x6 Entry Level USB Line devices" - -#elif defined(STM32F072xB) -#define PLATFORM_NAME "STM32F072xB Entry Level USB Line devices" - -#elif defined(STM32F038xx) -#define PLATFORM_NAME "STM32F038xx Entry Level Low Voltage Line devices" - -#elif defined(STM32F048xx) -#define PLATFORM_NAME "STM32F048xx Entry Level Low Voltage Line devices" - -#elif defined(STM32F058xx) -#define PLATFORM_NAME "STM32F058xx Entry Level Low Voltage Line devices" - -#elif defined(STM32F078xx) -#define PLATFORM_NAME "STM32F078xx Entry Level Low Voltage Line devices" - -#elif defined(STM32F098xx) -#define PLATFORM_NAME "STM32F098xx Entry Level Low Voltage Line devices" - -#else -#error "STM32F0xx device unsupported or not specified" -#endif -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @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 25000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 48000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB clock frequency. - */ -#define STM32_PCLK_MAX 48000000 -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 8000000 /**< High speed internal clock. */ -#define STM32_HSI14CLK 14000000 /**< 14MHz speed internal clock.*/ -#define STM32_HSI48CLK 48000000 /**< 48MHz speed internal clock.*/ -#define STM32_LSICLK 40000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @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 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ -#define STM32_SW_HSI48 (3 << 0) /**< SYSCLK source is HSI48. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PLLSRC_HSI_DIV2 (0 << 15) /**< PLL clock source is HSI/2. */ -#define STM32_PLLSRC_HSI (1 << 15) /**< PLL clock source is HSI */ -#define STM32_PLLSRC_HSE (2 << 15) /**< PLL clock source is HSE. */ -#define STM32_PLLSRC_HSI48 (3 << 15) /**< PLL clock source is HSI48. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_HSI14 (1 << 24) /**< HSI14 clock on MCO pin. */ -#define STM32_MCOSEL_LSI (2 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (3 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ - -#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ -#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ -#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ -#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ -#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ -#define STM32_MCOPRE_DIV32 (5 << 28) /**< MCO divided by 32. */ -#define STM32_MCOPRE_DIV64 (6 << 28) /**< MCO divided by 64. */ -#define STM32_MCOPRE_DIV128 (7 << 28) /**< MCO divided by 128. */ - -#define STM32_PLLNODIV_MASK (1 << 31) /**< MCO PLL divider mask. */ -#define STM32_PLLNODIV_DIV2 (0 << 31) /**< MCO PLL is divided by two. */ -#define STM32_PLLNODIV_DIV1 (1 << 31) /**< MCO PLL is divided by one. */ -/** @} */ - -/** - * @name RCC_CFGR2 register bits definitions - * @{ - */ -#define STM32_PRE_DIV1 (0 << 0) /**< PLLSRC divided by 1. */ -#define STM32_PRE_DIV2 (1 << 0) /**< SYSCLK divided by 2. */ -#define STM32_PRE_DIV3 (2 << 0) /**< SYSCLK divided by 3. */ -#define STM32_PRE_DIV4 (3 << 0) /**< PLLSRC divided by 4. */ -#define STM32_PRE_DIV5 (4 << 0) /**< SYSCLK divided by 5. */ -#define STM32_PRE_DIV6 (5 << 0) /**< SYSCLK divided by 6. */ -#define STM32_PRE_DIV7 (6 << 0) /**< PLLSRC divided by 7. */ -#define STM32_PRE_DIV8 (7 << 0) /**< SYSCLK divided by 8. */ -#define STM32_PRE_DIV9 (8 << 0) /**< SYSCLK divided by 9. */ -#define STM32_PRE_DIV10 (9 << 0) /**< PLLSRC divided by 10. */ -#define STM32_PRE_DIV11 (10 << 0) /**< SYSCLK divided by 11. */ -#define STM32_PRE_DIV12 (11 << 0) /**< SYSCLK divided by 12. */ -#define STM32_PRE_DIV13 (12 << 0) /**< PLLSRC divided by 13. */ -#define STM32_PRE_DIV14 (13 << 0) /**< SYSCLK divided by 14. */ -#define STM32_PRE_DIV15 (14 << 0) /**< SYSCLK divided by 15. */ -#define STM32_PRE_DIV16 (15 << 0) /**< PLLSRC divided by 16. */ -/** @} */ - -/** - * @name RCC_CFGR3 register bits definitions - * @{ - */ -#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ -#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ -#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ -#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ -#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ -#define STM32_I2C1SW_MASK (1 << 4) /**< I2C clock source mask. */ -#define STM32_I2C1SW_HSI (0 << 4) /**< I2C clock is HSI. */ -#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C clock is SYSCLK. */ -#define STM32_CECSW_MASK (1 << 6) /**< CEC clock source mask. */ -#define STM32_CECSW_HSI (0 << 6) /**< CEC clock is HSI/244. */ -#define STM32_CECSW_LSE (1 << 6) /**< CEC clock is LSE. */ -#define STM32_CECSW_OFF 0xFFFFFFFF /**< CEC clock is not required. */ -#define STM32_USBSW_MASK (1 << 7) /**< USB clock source mask. */ -#define STM32_USBSW_HSI48 (0 << 7) /**< USB clock is HSI48. */ -#define STM32_USBSW_PCLK (1 << 7) /**< USB clock is PCLK. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as - RTC clock. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSI14 clock source. - */ -#if !defined(STM32_HSI14_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI14_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSI48 clock source. - */ -#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI48_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV_VALUE 1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 6 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE) || defined(__DOXYGEN__) -#define STM32_PPRE STM32_PPRE_DIV1 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief MCO PLL divider setting. - */ -#if !defined(STM32_PLLNODIV) || defined(__DOXYGEN__) -#define STM32_PLLNODIV STM32_PLLNODIV_DIV2 -#endif - -/** - * @brief USB Clock source. - */ -#if !defined(STM32_USBSW) || defined(__DOXYGEN__) -#define STM32_USBSW STM32_USBSW_HSI48 -#endif - -/** - * @brief CEC clock source. - */ -#if !defined(STM32_CECSW) || defined(__DOXYGEN__) -#define STM32_CECSW STM32_CECSW_HSI -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) -#define STM32_I2C1SW STM32_I2C1SW_HSI -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) -#define STM32_USART1SW STM32_USART1SW_PCLK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F0xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F0xx_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#if (STM32_SW == STM32_SW_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) && !STM32_HAS_HSI_PREDIV -#error "STM32_PLLSRC_HSI not available on this platform. Select STM32_PLLSRC_HSI_DIV2 instead." -#endif -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if STM32_CECSW == STM32_CECSW_HSI -#error "HSI not enabled, required by STM32_CECSW" -#endif - -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#error "HSI not enabled, required by STM32_I2C1SW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_HSI -#error "HSI not enabled, required by STM32_USART1SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2) || \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - ((STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2) || \ - (STM32_PLLSRC == STM32_PLLSRC_HSI))) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSI14 related checks. - */ -#if STM32_HSI14_ENABLED -#else /* !STM32_HSI14_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_HSI14 -#error "HSI14 not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI14_ENABLED */ - -/* - * HSI48 related checks. - */ -#if STM32_HSI48_ENABLED -#if !STM32_HAS_HSI48 -#error "HSI48 not available on this platform" -#endif -#else /* !STM32_HSI48_ENABLED */ - -#if STM32_SW == STM32_SW_HSI48 -#error "HSI48 not enabled, required by STM32_SW" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI48) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - ((STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2) || \ - (STM32_PLLSRC == STM32_PLLSRC_HSI48))) -#error "HSI48 not enabled, required by STM32_MCOSEL" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI48) -#error "HSI48 not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#endif /* !STM32_HSI48_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_CECSW == STM32_CECSW_LSE -#error "LSE not enabled, required by STM32_CECSW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_LSE -#error "LSE not enabled, required by STM32_USART1SW" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_USBSW == STM32_USBSW_PCLK) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE, HSI prescaler setting check.*/ -#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) -#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) -#else -#error "invalid STM32_PREDIV value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2 -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PREDIV_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI48 -#define STM32_PLLCLKIN (STM32_HSI48CLK / STM32_PREDIV_VALUE) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL 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 - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSI48) -#define STM32_SYSCLK STM32_HSI48CLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB frequency. - */ -#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK (STM32_HCLK / 1) -#elif STM32_PPRE == STM32_PPRE_DIV2 -#define STM32_PCLK (STM32_HCLK / 2) -#elif STM32_PPRE == STM32_PPRE_DIV4 -#define STM32_PCLK (STM32_HCLK / 4) -#elif STM32_PPRE == STM32_PPRE_DIV8 -#define STM32_PCLK (STM32_HCLK / 8) -#elif STM32_PPRE == STM32_PPRE_DIV16 -#define STM32_PCLK (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE value specified" -#endif - -/* APB frequency check.*/ -#if STM32_PCLK > STM32_PCLK_MAX -#error "STM32_PCLK exceeding maximum frequency (STM32_PCLK_MAX)" -#endif - -/* STM32_PLLNODIV check.*/ -#if (STM32_PLLNODIV != STM32_PLLNODIV_DIV2) && \ - (STM32_PLLNODIV != STM32_PLLNODIV_DIV1) -#error "invalid STM32_PLLNODIV value specified" -#endif - -/** - * @brief MCO clock before divider. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 -#elif STM32_MCOSEL == STM32_MCOSEL_HSI14 -#define STM32_MCODIVCLK STM32_HSI14CLK -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK -#define STM32_MCODIVCLK STM32_SYSCLK -#elif STM32_MCOSEL == STM32_MCOSEL_HSI -#define STM32_MCODIVCLK STM32_HSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK -#elif STM32_MCOSEL == STM32_MCOSEL_PLLDIV2 -#if STM32_PLLNODIV == STM32_PLLNODIV_DIV2 -#define STM32_MCODIVCLK (STM32_PLLCLKOUT / 2) -#else -#define STM32_MCODIVCLK (STM32_PLLCLKOUT / 1) -#endif -#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 -#define STM32_MCODIVCLK STM32_HSI48CLK -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK -#elif (STM32_MCOPRE == STM32_MCOPRE_DIV2) && STM32_HAS_MCO_PREDIV -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) -#elif (STM32_MCOPRE == STM32_MCOPRE_DIV4) && STM32_HAS_MCO_PREDIV -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) -#elif (STM32_MCOPRE == STM32_MCOPRE_DIV8) && STM32_HAS_MCO_PREDIV -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) -#elif (STM32_MCOPRE == STM32_MCOPRE_DIV16) && STM32_HAS_MCO_PREDIV -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) -#elif !STM32_HAS_MCO_PREDIV -#error "MCO_PREDIV not available on this platform. Select STM32_MCODIVCLK." -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief USB frequency. - */ -#if (STM32_USBSW == STM32_USBSW_HSI48) || defined(__DOXYGEN__) -#define STM32_USBCLK STM32_HSI48CLK -#elif STM32_USBSW == STM32_USBSW_PCLK -#define STM32_USBCLK STM32_PLLCLKOUT -#else -#error "invalid source selected for USB clock" -#endif - -/** - * @brief CEC frequency. - */ -#if (STM32_CECSW == STM32_CECSW_HSI) || defined(__DOXYGEN__) -#define STM32_CECCLK STM32_HSICLK -#elif STM32_CECSW == STM32_CECSW_LSE -#define STM32_CECCLK STM32_LSECLK -#elif STM32_CECSW == STM32_CECSW_OFF -#define STM32_CECCLK 0 -#else -#error "invalid source selected for CEC clock" -#endif - -/** - * @brief I2C1 frequency. - */ -#if (STM32_I2C1SW == STM32_I2C1SW_HSI) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_HSICLK -#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief USART1 frequency. - */ -#if (STM32_USART1SW == STM32_USART1SW_PCLK) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK -#elif STM32_USART1SW == STM32_USART1SW_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SW == STM32_USART1SW_LSE -#define STM32_USART1CLK STM32_LSECLK -#elif STM32_USART1SW == STM32_USART1SW_HSI -#define STM32_USART1CLK STM32_HSICLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#define STM32_USART2CLK STM32_PCLK - -/** - * @brief USART3 frequency. - */ -#define STM32_USART3CLK STM32_PCLK - -/** - * @brief USART4 frequency. - */ -#define STM32_UART4CLK STM32_PCLK - -/** - * @brief USART5 frequency. - */ -#define STM32_UART5CLK STM32_PCLK - -/** - * @brief USART6 frequency. - */ -#define STM32_USART6CLK STM32_PCLK - -/** - * @brief USART7 frequency. - */ -#define STM32_UART7CLK STM32_PCLK - -/** - * @brief USART8 frequency. - */ -#define STM32_UART8CLK STM32_PCLK - -/** - * @brief Timers clock. - */ -#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK * 1) -#define STM32_TIMCLK2 (STM32_PCLK * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK * 2) -#define STM32_TIMCLK2 (STM32_PCLK * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#else -#define STM32_FLASHBITS 0x00000011 -#endif - -/* - * For compatibility with driver assuming a specific PPRE clock. - */ -#define STM32_PCLK1 STM32_PCLK -#define STM32_PCLK2 STM32_PCLK - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/hal_lld.h + * @brief STM32F0xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32F030x4, STM32F030x6, STM32F030x8, STM32F030xC, + * STM32F070x6, STM32F070xB for Value Line devices. + * - STM32F031x6, STM32F051x8, STM32F071xB, STM32F091xC + * for Access Line devices. + * - STM32F042x6, STM32F072xB for USB Line devices. + * - STM32F038xx, STM32F048xx, STM32F058xx, STM32F078xx, + * STM32F098xx for Low Voltage Line devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +/* + * Registry definitions. + */ +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32F030x4) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F030x4 Entry Level Value Line devices" + +#elif defined(STM32F030x6) +#define PLATFORM_NAME "STM32F030x6 Entry Level Value Line devices" + +#elif defined(STM32F030x8) +#define PLATFORM_NAME "STM32F030x8 Entry Level Value Line devices" + +#elif defined(STM32F030xC) +#define PLATFORM_NAME "STM32F030xC Entry Level Value Line devices" + +#elif defined(STM32F070x6) +#define PLATFORM_NAME "STM32F070x6 Entry Level Value Line devices" + +#elif defined(STM32F070xB) +#define PLATFORM_NAME "STM32F070xB Entry Level Value Line devices" + +#elif defined(STM32F031x6) +#define PLATFORM_NAME "STM32F031x6 Entry Level Access Line devices" + +#elif defined(STM32F051x8) +#define PLATFORM_NAME "STM32F051x8 Entry Level Access Line devices" + +#elif defined(STM32F071xB) +#define PLATFORM_NAME "STM32F071xB Entry Level Access Line devices" + +#elif defined(STM32F091xC) +#define PLATFORM_NAME "STM32F091xC Entry Level Access Line devices" + +#elif defined(STM32F042x6) +#define PLATFORM_NAME "STM32F042x6 Entry Level USB Line devices" + +#elif defined(STM32F072xB) +#define PLATFORM_NAME "STM32F072xB Entry Level USB Line devices" + +#elif defined(STM32F038xx) +#define PLATFORM_NAME "STM32F038xx Entry Level Low Voltage Line devices" + +#elif defined(STM32F048xx) +#define PLATFORM_NAME "STM32F048xx Entry Level Low Voltage Line devices" + +#elif defined(STM32F058xx) +#define PLATFORM_NAME "STM32F058xx Entry Level Low Voltage Line devices" + +#elif defined(STM32F078xx) +#define PLATFORM_NAME "STM32F078xx Entry Level Low Voltage Line devices" + +#elif defined(STM32F098xx) +#define PLATFORM_NAME "STM32F098xx Entry Level Low Voltage Line devices" + +#else +#error "STM32F0xx device unsupported or not specified" +#endif +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @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 25000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 48000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB clock frequency. + */ +#define STM32_PCLK_MAX 48000000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 8000000 /**< High speed internal clock. */ +#define STM32_HSI14CLK 14000000 /**< 14MHz speed internal clock.*/ +#define STM32_HSI48CLK 48000000 /**< 48MHz speed internal clock.*/ +#define STM32_LSICLK 40000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @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 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ +#define STM32_SW_HSI48 (3 << 0) /**< SYSCLK source is HSI48. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PLLSRC_HSI_DIV2 (0 << 15) /**< PLL clock source is HSI/2. */ +#define STM32_PLLSRC_HSI (1 << 15) /**< PLL clock source is HSI */ +#define STM32_PLLSRC_HSE (2 << 15) /**< PLL clock source is HSE. */ +#define STM32_PLLSRC_HSI48 (3 << 15) /**< PLL clock source is HSI48. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_HSI14 (1 << 24) /**< HSI14 clock on MCO pin. */ +#define STM32_MCOSEL_LSI (2 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (3 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ + +#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ +#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ +#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ +#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ +#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ +#define STM32_MCOPRE_DIV32 (5 << 28) /**< MCO divided by 32. */ +#define STM32_MCOPRE_DIV64 (6 << 28) /**< MCO divided by 64. */ +#define STM32_MCOPRE_DIV128 (7 << 28) /**< MCO divided by 128. */ + +#define STM32_PLLNODIV_MASK (1 << 31) /**< MCO PLL divider mask. */ +#define STM32_PLLNODIV_DIV2 (0 << 31) /**< MCO PLL is divided by two. */ +#define STM32_PLLNODIV_DIV1 (1 << 31) /**< MCO PLL is divided by one. */ +/** @} */ + +/** + * @name RCC_CFGR2 register bits definitions + * @{ + */ +#define STM32_PRE_DIV1 (0 << 0) /**< PLLSRC divided by 1. */ +#define STM32_PRE_DIV2 (1 << 0) /**< SYSCLK divided by 2. */ +#define STM32_PRE_DIV3 (2 << 0) /**< SYSCLK divided by 3. */ +#define STM32_PRE_DIV4 (3 << 0) /**< PLLSRC divided by 4. */ +#define STM32_PRE_DIV5 (4 << 0) /**< SYSCLK divided by 5. */ +#define STM32_PRE_DIV6 (5 << 0) /**< SYSCLK divided by 6. */ +#define STM32_PRE_DIV7 (6 << 0) /**< PLLSRC divided by 7. */ +#define STM32_PRE_DIV8 (7 << 0) /**< SYSCLK divided by 8. */ +#define STM32_PRE_DIV9 (8 << 0) /**< SYSCLK divided by 9. */ +#define STM32_PRE_DIV10 (9 << 0) /**< PLLSRC divided by 10. */ +#define STM32_PRE_DIV11 (10 << 0) /**< SYSCLK divided by 11. */ +#define STM32_PRE_DIV12 (11 << 0) /**< SYSCLK divided by 12. */ +#define STM32_PRE_DIV13 (12 << 0) /**< PLLSRC divided by 13. */ +#define STM32_PRE_DIV14 (13 << 0) /**< SYSCLK divided by 14. */ +#define STM32_PRE_DIV15 (14 << 0) /**< SYSCLK divided by 15. */ +#define STM32_PRE_DIV16 (15 << 0) /**< PLLSRC divided by 16. */ +/** @} */ + +/** + * @name RCC_CFGR3 register bits definitions + * @{ + */ +#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ +#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ +#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ +#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ +#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ +#define STM32_I2C1SW_MASK (1 << 4) /**< I2C clock source mask. */ +#define STM32_I2C1SW_HSI (0 << 4) /**< I2C clock is HSI. */ +#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C clock is SYSCLK. */ +#define STM32_CECSW_MASK (1 << 6) /**< CEC clock source mask. */ +#define STM32_CECSW_HSI (0 << 6) /**< CEC clock is HSI/244. */ +#define STM32_CECSW_LSE (1 << 6) /**< CEC clock is LSE. */ +#define STM32_CECSW_OFF 0xFFFFFFFF /**< CEC clock is not required. */ +#define STM32_USBSW_MASK (1 << 7) /**< USB clock source mask. */ +#define STM32_USBSW_HSI48 (0 << 7) /**< USB clock is HSI48. */ +#define STM32_USBSW_PCLK (1 << 7) /**< USB clock is PCLK. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as + RTC clock. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSI14 clock source. + */ +#if !defined(STM32_HSI14_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI14_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSI48 clock source. + */ +#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI48_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV_VALUE 1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 6 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE) || defined(__DOXYGEN__) +#define STM32_PPRE STM32_PPRE_DIV1 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief MCO PLL divider setting. + */ +#if !defined(STM32_PLLNODIV) || defined(__DOXYGEN__) +#define STM32_PLLNODIV STM32_PLLNODIV_DIV2 +#endif + +/** + * @brief USB Clock source. + */ +#if !defined(STM32_USBSW) || defined(__DOXYGEN__) +#define STM32_USBSW STM32_USBSW_HSI48 +#endif + +/** + * @brief CEC clock source. + */ +#if !defined(STM32_CECSW) || defined(__DOXYGEN__) +#define STM32_CECSW STM32_CECSW_HSI +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) +#define STM32_I2C1SW STM32_I2C1SW_HSI +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) +#define STM32_USART1SW STM32_USART1SW_PCLK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F0xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F0xx_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#if (STM32_SW == STM32_SW_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) && !STM32_HAS_HSI_PREDIV +#error "STM32_PLLSRC_HSI not available on this platform. Select STM32_PLLSRC_HSI_DIV2 instead." +#endif +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if STM32_CECSW == STM32_CECSW_HSI +#error "HSI not enabled, required by STM32_CECSW" +#endif + +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#error "HSI not enabled, required by STM32_I2C1SW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_HSI +#error "HSI not enabled, required by STM32_USART1SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2) || \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + ((STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2) || \ + (STM32_PLLSRC == STM32_PLLSRC_HSI))) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSI14 related checks. + */ +#if STM32_HSI14_ENABLED +#else /* !STM32_HSI14_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_HSI14 +#error "HSI14 not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI14_ENABLED */ + +/* + * HSI48 related checks. + */ +#if STM32_HSI48_ENABLED +#if !STM32_HAS_HSI48 +#error "HSI48 not available on this platform" +#endif +#else /* !STM32_HSI48_ENABLED */ + +#if STM32_SW == STM32_SW_HSI48 +#error "HSI48 not enabled, required by STM32_SW" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI48) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + ((STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2) || \ + (STM32_PLLSRC == STM32_PLLSRC_HSI48))) +#error "HSI48 not enabled, required by STM32_MCOSEL" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI48) +#error "HSI48 not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#endif /* !STM32_HSI48_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if STM32_CECSW == STM32_CECSW_LSE +#error "LSE not enabled, required by STM32_CECSW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_LSE +#error "LSE not enabled, required by STM32_USART1SW" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_USBSW == STM32_USBSW_PCLK) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE, HSI prescaler setting check.*/ +#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) +#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) +#else +#error "invalid STM32_PREDIV value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI_DIV2 +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PREDIV_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI48 +#define STM32_PLLCLKIN (STM32_HSI48CLK / STM32_PREDIV_VALUE) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL 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 + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSI48) +#define STM32_SYSCLK STM32_HSI48CLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB frequency. + */ +#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK (STM32_HCLK / 1) +#elif STM32_PPRE == STM32_PPRE_DIV2 +#define STM32_PCLK (STM32_HCLK / 2) +#elif STM32_PPRE == STM32_PPRE_DIV4 +#define STM32_PCLK (STM32_HCLK / 4) +#elif STM32_PPRE == STM32_PPRE_DIV8 +#define STM32_PCLK (STM32_HCLK / 8) +#elif STM32_PPRE == STM32_PPRE_DIV16 +#define STM32_PCLK (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE value specified" +#endif + +/* APB frequency check.*/ +#if STM32_PCLK > STM32_PCLK_MAX +#error "STM32_PCLK exceeding maximum frequency (STM32_PCLK_MAX)" +#endif + +/* STM32_PLLNODIV check.*/ +#if (STM32_PLLNODIV != STM32_PLLNODIV_DIV2) && \ + (STM32_PLLNODIV != STM32_PLLNODIV_DIV1) +#error "invalid STM32_PLLNODIV value specified" +#endif + +/** + * @brief MCO clock before divider. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 +#elif STM32_MCOSEL == STM32_MCOSEL_HSI14 +#define STM32_MCODIVCLK STM32_HSI14CLK +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK +#define STM32_MCODIVCLK STM32_SYSCLK +#elif STM32_MCOSEL == STM32_MCOSEL_HSI +#define STM32_MCODIVCLK STM32_HSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK +#elif STM32_MCOSEL == STM32_MCOSEL_PLLDIV2 +#if STM32_PLLNODIV == STM32_PLLNODIV_DIV2 +#define STM32_MCODIVCLK (STM32_PLLCLKOUT / 2) +#else +#define STM32_MCODIVCLK (STM32_PLLCLKOUT / 1) +#endif +#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 +#define STM32_MCODIVCLK STM32_HSI48CLK +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK +#elif (STM32_MCOPRE == STM32_MCOPRE_DIV2) && STM32_HAS_MCO_PREDIV +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) +#elif (STM32_MCOPRE == STM32_MCOPRE_DIV4) && STM32_HAS_MCO_PREDIV +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) +#elif (STM32_MCOPRE == STM32_MCOPRE_DIV8) && STM32_HAS_MCO_PREDIV +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) +#elif (STM32_MCOPRE == STM32_MCOPRE_DIV16) && STM32_HAS_MCO_PREDIV +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) +#elif !STM32_HAS_MCO_PREDIV +#error "MCO_PREDIV not available on this platform. Select STM32_MCODIVCLK." +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief USB frequency. + */ +#if (STM32_USBSW == STM32_USBSW_HSI48) || defined(__DOXYGEN__) +#define STM32_USBCLK STM32_HSI48CLK +#elif STM32_USBSW == STM32_USBSW_PCLK +#define STM32_USBCLK STM32_PLLCLKOUT +#else +#error "invalid source selected for USB clock" +#endif + +/** + * @brief CEC frequency. + */ +#if (STM32_CECSW == STM32_CECSW_HSI) || defined(__DOXYGEN__) +#define STM32_CECCLK STM32_HSICLK +#elif STM32_CECSW == STM32_CECSW_LSE +#define STM32_CECCLK STM32_LSECLK +#elif STM32_CECSW == STM32_CECSW_OFF +#define STM32_CECCLK 0 +#else +#error "invalid source selected for CEC clock" +#endif + +/** + * @brief I2C1 frequency. + */ +#if (STM32_I2C1SW == STM32_I2C1SW_HSI) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_HSICLK +#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief USART1 frequency. + */ +#if (STM32_USART1SW == STM32_USART1SW_PCLK) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK +#elif STM32_USART1SW == STM32_USART1SW_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SW == STM32_USART1SW_LSE +#define STM32_USART1CLK STM32_LSECLK +#elif STM32_USART1SW == STM32_USART1SW_HSI +#define STM32_USART1CLK STM32_HSICLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#define STM32_USART2CLK STM32_PCLK + +/** + * @brief USART3 frequency. + */ +#define STM32_USART3CLK STM32_PCLK + +/** + * @brief USART4 frequency. + */ +#define STM32_UART4CLK STM32_PCLK + +/** + * @brief USART5 frequency. + */ +#define STM32_UART5CLK STM32_PCLK + +/** + * @brief USART6 frequency. + */ +#define STM32_USART6CLK STM32_PCLK + +/** + * @brief USART7 frequency. + */ +#define STM32_UART7CLK STM32_PCLK + +/** + * @brief USART8 frequency. + */ +#define STM32_UART8CLK STM32_PCLK + +/** + * @brief Timers clock. + */ +#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK * 1) +#define STM32_TIMCLK2 (STM32_PCLK * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK * 2) +#define STM32_TIMCLK2 (STM32_PCLK * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#else +#define STM32_FLASHBITS 0x00000011 +#endif + +/* + * For compatibility with driver assuming a specific PPRE clock. + */ +#define STM32_PCLK1 STM32_PCLK +#define STM32_PCLK2 STM32_PCLK + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F0xx/platform.mk b/os/hal/ports/STM32/STM32F0xx/platform.mk index b8975be7eb..276f3556ae 100644 --- a/os/hal/ports/STM32/STM32F0xx/platform.mk +++ b/os/hal/ports/STM32/STM32F0xx/platform.mk @@ -1,44 +1,44 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F0xx/stm32_isr.c b/os/hal/ports/STM32/STM32F0xx/stm32_isr.c index 489388e24a..6077862e1b 100644 --- a/os/hal/ports/STM32/STM32F0xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32F0xx/stm32_isr.c @@ -1,286 +1,286 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_isr.c - * @brief STM32F0xx ISR handler code. - * - * @addtogroup STM32F0xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_EXTI0_1_HANDLER) -/** - * @brief EXTI[0]...EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector54) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= ((1U << 0) | (1U << 1)); - EXTI->PR = pr; - - exti_serve_irq(pr, 0); - exti_serve_irq(pr, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_3_HANDLER) -/** - * @brief EXTI[2]...EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= ((1U << 2) | (1U << 3)); - EXTI->PR = pr; - - exti_serve_irq(pr, 2); - exti_serve_irq(pr, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_15_HANDLER) -/** - * @brief EXTI[4]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= ((1U << 4) | (1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | - (1U << 9) | (1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | - (1U << 14) | (1U << 15)); - EXTI->PR = pr; - - exti_serve_irq(pr, 4); - exti_serve_irq(pr, 5); - exti_serve_irq(pr, 6); - exti_serve_irq(pr, 7); - exti_serve_irq(pr, 8); - exti_serve_irq(pr, 9); - exti_serve_irq(pr, 10); - exti_serve_irq(pr, 11); - exti_serve_irq(pr, 12); - exti_serve_irq(pr, 13); - exti_serve_irq(pr, 14); - exti_serve_irq(pr, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ - -#if HAL_USE_SERIAL || HAL_USE_UART || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_USART1_HANDLER) -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_SERIAL -#if STM32_SERIAL_USE_USART1 - sd_lld_serve_interrupt(&SD1); -#endif -#endif -#if HAL_USE_UART -#if STM32_UART_USE_USART1 - uart_lld_serve_interrupt(&UARTD1); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_USART2_HANDLER) -/** - * @brief USART2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_SERIAL -#if STM32_SERIAL_USE_USART2 - sd_lld_serve_interrupt(&SD2); -#endif -#endif -#if HAL_USE_UART -#if STM32_UART_USE_USART2 - uart_lld_serve_interrupt(&UARTD2); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_USART38_HANDLER) -/** - * @brief USART3..8 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_8_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_SERIAL -#if STM32_SERIAL_USE_USART3 - sd_lld_serve_interrupt(&SD3); -#endif -#if STM32_SERIAL_USE_UART4 - sd_lld_serve_interrupt(&SD4); -#endif -#if STM32_SERIAL_USE_UART5 - sd_lld_serve_interrupt(&SD5); -#endif -#if STM32_SERIAL_USE_USART6 - sd_lld_serve_interrupt(&SD6); -#endif -#if STM32_SERIAL_USE_UART7 - sd_lld_serve_interrupt(&SD7); -#endif -#if STM32_SERIAL_USE_UART8 - sd_lld_serve_interrupt(&SD8); -#endif -#endif -#if HAL_USE_UART -#if STM32_UART_USE_USART3 - uart_lld_serve_interrupt(&UARTD3); -#endif -#if STM32_UART_USE_UART4 - uart_lld_serve_interrupt(&UARTD4); -#endif -#if STM32_UART_USE_UART5 - uart_lld_serve_interrupt(&UARTD5); -#endif -#if STM32_UART_USE_USART6 - uart_lld_serve_interrupt(&UARTD6); -#endif -#if STM32_UART_USE_UART7 - uart_lld_serve_interrupt(&UARTD7); -#endif -#if STM32_UART_USE_UART8 - uart_lld_serve_interrupt(&UARTD8); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif /* HAL_USE_SERIAL || HAL_USE_UART */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - -#if HAL_USE_PAL - nvicEnableVector(EXTI0_1_IRQn, STM32_IRQ_EXTI0_1_PRIORITY); - nvicEnableVector(EXTI2_3_IRQn, STM32_IRQ_EXTI2_3_PRIORITY); - nvicEnableVector(EXTI4_15_IRQn, STM32_IRQ_EXTI4_15_PRIORITY); -#endif - -#if HAL_USE_SERIAL || HAL_USE_UART - nvicEnableVector(STM32_USART1_NUMBER, STM32_IRQ_USART1_PRIORITY); - nvicEnableVector(STM32_USART2_NUMBER, STM32_IRQ_USART2_PRIORITY); - nvicEnableVector(STM32_USART3_8_NUMBER, STM32_IRQ_USART3_8_PRIORITY); -#endif -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - -#if HAL_USE_PAL - nvicDisableVector(EXTI0_1_IRQn); - nvicDisableVector(EXTI2_3_IRQn); - nvicDisableVector(EXTI4_15_IRQn); -#endif - -#if HAL_USE_SERIAL || HAL_USE_UART - nvicDisableVector(STM32_USART1_NUMBER); - nvicDisableVector(STM32_USART2_NUMBER); - nvicDisableVector(STM32_USART3_8_NUMBER); -#endif -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_isr.c + * @brief STM32F0xx ISR handler code. + * + * @addtogroup STM32F0xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_EXTI0_1_HANDLER) +/** + * @brief EXTI[0]...EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector54) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= ((1U << 0) | (1U << 1)); + EXTI->PR = pr; + + exti_serve_irq(pr, 0); + exti_serve_irq(pr, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_3_HANDLER) +/** + * @brief EXTI[2]...EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= ((1U << 2) | (1U << 3)); + EXTI->PR = pr; + + exti_serve_irq(pr, 2); + exti_serve_irq(pr, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_15_HANDLER) +/** + * @brief EXTI[4]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= ((1U << 4) | (1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | + (1U << 9) | (1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | + (1U << 14) | (1U << 15)); + EXTI->PR = pr; + + exti_serve_irq(pr, 4); + exti_serve_irq(pr, 5); + exti_serve_irq(pr, 6); + exti_serve_irq(pr, 7); + exti_serve_irq(pr, 8); + exti_serve_irq(pr, 9); + exti_serve_irq(pr, 10); + exti_serve_irq(pr, 11); + exti_serve_irq(pr, 12); + exti_serve_irq(pr, 13); + exti_serve_irq(pr, 14); + exti_serve_irq(pr, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ + +#if HAL_USE_SERIAL || HAL_USE_UART || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_USART1_HANDLER) +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_SERIAL +#if STM32_SERIAL_USE_USART1 + sd_lld_serve_interrupt(&SD1); +#endif +#endif +#if HAL_USE_UART +#if STM32_UART_USE_USART1 + uart_lld_serve_interrupt(&UARTD1); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_USART2_HANDLER) +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_SERIAL +#if STM32_SERIAL_USE_USART2 + sd_lld_serve_interrupt(&SD2); +#endif +#endif +#if HAL_USE_UART +#if STM32_UART_USE_USART2 + uart_lld_serve_interrupt(&UARTD2); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_USART38_HANDLER) +/** + * @brief USART3..8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_SERIAL +#if STM32_SERIAL_USE_USART3 + sd_lld_serve_interrupt(&SD3); +#endif +#if STM32_SERIAL_USE_UART4 + sd_lld_serve_interrupt(&SD4); +#endif +#if STM32_SERIAL_USE_UART5 + sd_lld_serve_interrupt(&SD5); +#endif +#if STM32_SERIAL_USE_USART6 + sd_lld_serve_interrupt(&SD6); +#endif +#if STM32_SERIAL_USE_UART7 + sd_lld_serve_interrupt(&SD7); +#endif +#if STM32_SERIAL_USE_UART8 + sd_lld_serve_interrupt(&SD8); +#endif +#endif +#if HAL_USE_UART +#if STM32_UART_USE_USART3 + uart_lld_serve_interrupt(&UARTD3); +#endif +#if STM32_UART_USE_UART4 + uart_lld_serve_interrupt(&UARTD4); +#endif +#if STM32_UART_USE_UART5 + uart_lld_serve_interrupt(&UARTD5); +#endif +#if STM32_UART_USE_USART6 + uart_lld_serve_interrupt(&UARTD6); +#endif +#if STM32_UART_USE_UART7 + uart_lld_serve_interrupt(&UARTD7); +#endif +#if STM32_UART_USE_UART8 + uart_lld_serve_interrupt(&UARTD8); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif /* HAL_USE_SERIAL || HAL_USE_UART */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + +#if HAL_USE_PAL + nvicEnableVector(EXTI0_1_IRQn, STM32_IRQ_EXTI0_1_PRIORITY); + nvicEnableVector(EXTI2_3_IRQn, STM32_IRQ_EXTI2_3_PRIORITY); + nvicEnableVector(EXTI4_15_IRQn, STM32_IRQ_EXTI4_15_PRIORITY); +#endif + +#if HAL_USE_SERIAL || HAL_USE_UART + nvicEnableVector(STM32_USART1_NUMBER, STM32_IRQ_USART1_PRIORITY); + nvicEnableVector(STM32_USART2_NUMBER, STM32_IRQ_USART2_PRIORITY); + nvicEnableVector(STM32_USART3_8_NUMBER, STM32_IRQ_USART3_8_PRIORITY); +#endif +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +#if HAL_USE_PAL + nvicDisableVector(EXTI0_1_IRQn); + nvicDisableVector(EXTI2_3_IRQn); + nvicDisableVector(EXTI4_15_IRQn); +#endif + +#if HAL_USE_SERIAL || HAL_USE_UART + nvicDisableVector(STM32_USART1_NUMBER); + nvicDisableVector(STM32_USART2_NUMBER); + nvicDisableVector(STM32_USART3_8_NUMBER); +#endif +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F0xx/stm32_isr.h b/os/hal/ports/STM32/STM32F0xx/stm32_isr.h index e3ebc44faf..25b4cef356 100644 --- a/os/hal/ports/STM32/STM32F0xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F0xx/stm32_isr.h @@ -1,246 +1,246 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_isr.h - * @brief STM32F0xx ISR handler header. - * - * @addtogroup STM32F0xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_USART6_SUPPRESS_ISR -#define STM32_UART7_SUPPRESS_ISR -#define STM32_UART8_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_UNIFIED_HANDLER VectorB8 -#define STM32_CAN1_UNIFIED_NUMBER 30 - -/* - * I2C units. - */ -#define STM32_I2C1_GLOBAL_HANDLER Vector9C -#define STM32_I2C1_GLOBAL_NUMBER 23 - -#define STM32_I2C2_GLOBAL_HANDLER VectorA0 -#define STM32_I2C2_GLOBAL_NUMBER 24 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER Vector74 -#define STM32_TIM1_CC_HANDLER Vector78 -#define STM32_TIM2_HANDLER Vector7C -#define STM32_TIM3_HANDLER Vector80 -#define STM32_TIM6_HANDLER Vector84 -#define STM32_TIM7_HANDLER Vector88 -#define STM32_TIM14_HANDLER Vector8C -#define STM32_TIM15_HANDLER Vector90 -#define STM32_TIM16_HANDLER Vector94 -#define STM32_TIM17_HANDLER Vector98 - -#define STM32_TIM1_UP_NUMBER 13 -#define STM32_TIM1_CC_NUMBER 14 -#define STM32_TIM2_NUMBER 15 -#define STM32_TIM3_NUMBER 16 -#define STM32_TIM6_NUMBER 17 -#define STM32_TIM7_NUMBER 18 -#define STM32_TIM14_NUMBER 19 -#define STM32_TIM15_NUMBER 20 -#define STM32_TIM16_NUMBER 21 -#define STM32_TIM17_NUMBER 22 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorAC -#define STM32_USART2_HANDLER VectorB0 -#define STM32_USART3_8_HANDLER VectorB4 - -#define STM32_USART1_NUMBER 27 -#define STM32_USART2_NUMBER 28 -#define STM32_USART3_8_NUMBER 29 - -/* - * USB units. - */ -#define STM32_USB1_LP_HANDLER VectorBC -#define STM32_USB1_LP_NUMBER 31 -#define STM32_USB1_HP_HANDLER VectorBC -#define STM32_USB1_HP_NUMBER 31 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0..1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI0_1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI0_1_PRIORITY 3 -#endif - -/** - * @brief EXTI2..3 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI2_3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI2_3_PRIORITY 3 -#endif - -/** - * @brief EXTI4..15 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI4_15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI4_15_PRIORITY 3 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI16_PRIORITY 3 -#endif - -/** - * @brief EXTI17,19,20 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI17_20_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI17_20_PRIORITY 3 -#endif - -/** - * @brief EXTI21,22 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI21_22_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI21_22_PRIORITY 3 -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_USART1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_USART1_PRIORITY 3 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_USART2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_USART2_PRIORITY 3 -#endif - -/** - * @brief USART3..8 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_USART3_8_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_USART3_8_PRIORITY 3 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* IRQ priority checks.*/ -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI0_1_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI0_1_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI2_3_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI2_3_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI4_15_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI4_15_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI16_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI16_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI17_20_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI17_20_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI21_22_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI21_22_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART1_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_USART1_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART2_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_USART2_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART3_8_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_USART3_8_PRIORITY" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_isr.h + * @brief STM32F0xx ISR handler header. + * + * @addtogroup STM32F0xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_USART6_SUPPRESS_ISR +#define STM32_UART7_SUPPRESS_ISR +#define STM32_UART8_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_UNIFIED_HANDLER VectorB8 +#define STM32_CAN1_UNIFIED_NUMBER 30 + +/* + * I2C units. + */ +#define STM32_I2C1_GLOBAL_HANDLER Vector9C +#define STM32_I2C1_GLOBAL_NUMBER 23 + +#define STM32_I2C2_GLOBAL_HANDLER VectorA0 +#define STM32_I2C2_GLOBAL_NUMBER 24 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER Vector74 +#define STM32_TIM1_CC_HANDLER Vector78 +#define STM32_TIM2_HANDLER Vector7C +#define STM32_TIM3_HANDLER Vector80 +#define STM32_TIM6_HANDLER Vector84 +#define STM32_TIM7_HANDLER Vector88 +#define STM32_TIM14_HANDLER Vector8C +#define STM32_TIM15_HANDLER Vector90 +#define STM32_TIM16_HANDLER Vector94 +#define STM32_TIM17_HANDLER Vector98 + +#define STM32_TIM1_UP_NUMBER 13 +#define STM32_TIM1_CC_NUMBER 14 +#define STM32_TIM2_NUMBER 15 +#define STM32_TIM3_NUMBER 16 +#define STM32_TIM6_NUMBER 17 +#define STM32_TIM7_NUMBER 18 +#define STM32_TIM14_NUMBER 19 +#define STM32_TIM15_NUMBER 20 +#define STM32_TIM16_NUMBER 21 +#define STM32_TIM17_NUMBER 22 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorAC +#define STM32_USART2_HANDLER VectorB0 +#define STM32_USART3_8_HANDLER VectorB4 + +#define STM32_USART1_NUMBER 27 +#define STM32_USART2_NUMBER 28 +#define STM32_USART3_8_NUMBER 29 + +/* + * USB units. + */ +#define STM32_USB1_LP_HANDLER VectorBC +#define STM32_USB1_LP_NUMBER 31 +#define STM32_USB1_HP_HANDLER VectorBC +#define STM32_USB1_HP_NUMBER 31 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0..1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI0_1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI0_1_PRIORITY 3 +#endif + +/** + * @brief EXTI2..3 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI2_3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI2_3_PRIORITY 3 +#endif + +/** + * @brief EXTI4..15 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI4_15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI4_15_PRIORITY 3 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI16_PRIORITY 3 +#endif + +/** + * @brief EXTI17,19,20 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI17_20_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI17_20_PRIORITY 3 +#endif + +/** + * @brief EXTI21,22 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI21_22_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI21_22_PRIORITY 3 +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_USART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_USART1_PRIORITY 3 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_USART2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_USART2_PRIORITY 3 +#endif + +/** + * @brief USART3..8 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_USART3_8_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_USART3_8_PRIORITY 3 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* IRQ priority checks.*/ +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI0_1_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI0_1_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI2_3_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI2_3_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI4_15_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI4_15_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI16_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI16_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI17_20_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI17_20_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI21_22_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI21_22_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART1_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_USART1_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART2_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_USART2_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART3_8_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_USART3_8_PRIORITY" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F0xx/stm32_rcc.h b/os/hal/ports/STM32/STM32F0xx/stm32_rcc.h index 94bc779558..b0ef86d1f7 100644 --- a/os/hal/ports/STM32/STM32F0xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32F0xx/stm32_rcc.h @@ -1,965 +1,965 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f0xx.h. - * - * @addtogroup STM32F0xx_RCC - * @{ - */ - -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1(mask, lp) { \ - RCC->APB1ENR |= (mask); \ - (void)RCC->APB1ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - (void)RCC->APB1ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB2 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB2(mask, lp) { \ - RCC->APB2ENR |= (mask); \ - (void)RCC->APB2ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - (void)RCC->APB2ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CANEN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CANEN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CANRST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name DMA peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetDMA1() - -/** - * @brief Enables the DMA2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetDMA2() -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @brief Resets the SPI1 peripheral. - * - * @api - */ -#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) - -/** - * @brief Enables the SPI2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @brief Resets the TIM1 peripheral. - * - * @api - */ -#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) - -/** - * @brief Enables the TIM2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) - -/** - * @brief Enables the USART2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the USART4 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_USART4EN, lp) - -/** - * @brief Disables the USART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_USART4EN) - -/** - * @brief Resets the USART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_USART4RST) - -/** - * @brief Enables the USART5 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_USART5EN, lp) - -/** - * @brief Disables the USART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_USART5EN) - -/** - * @brief Resets the USART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_USART5RST) - -/** - * @brief Enables the USART6 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp) - -/** - * @brief Disables the USART6 peripheral clock. - * - * @api - */ -#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) - -/** - * @brief Resets the USART6 peripheral. - * - * @api - */ -#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) - -/** - * @brief Enables the UART7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART7(lp) rccEnableAPB2(RCC_APB2ENR_USART7EN, lp) - -/** - * @brief Disables the UART7 peripheral clock. - * - * @api - */ -#define rccDisableUART7() rccDisableAPB2(RCC_APB2ENR_USART7EN) - -/** - * @brief Resets the UART7 peripheral. - * - * @api - */ -#define rccResetUART7() rccResetAPB2(RCC_APB2RSTR_USART7RST) - -/** - * @brief Enables the UART8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART8(lp) rccEnableAPB2(RCC_APB2ENR_USART8EN, lp) - -/** - * @brief Disables the UART8 peripheral clock. - * - * @api - */ -#define rccDisableUART8() rccDisableAPB2(RCC_APB2ENR_USART8EN) - -/** - * @brief Resets the UART8 peripheral. - * - * @api - */ -#define rccResetUART8() rccResetAPB2(RCC_APB2RSTR_USART8RST) -/** @} */ - -/** - * @name USB peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/** - * @name CRC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST) -/** @} */ - -/** - * @name WWDG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the WWDG peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableWWDG(lp) rccEnableAPB1(RCC_APB1ENR_WWDGEN, lp) - -/** - * @brief Disables the WWDG peripheral clock. - * - * @api - */ -#define rccDisableWWDG() rccDisableAPB1(RCC_APB1ENR_WWDGEN) - -/** - * @brief Resets the WWDG peripheral. - * - * @api - */ -#define rccResetWWDG() rccResetAPB1(RCC_APB1RSTR_WWDGRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f0xx.h. + * + * @addtogroup STM32F0xx_RCC + * @{ + */ + +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1(mask, lp) { \ + RCC->APB1ENR |= (mask); \ + (void)RCC->APB1ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + (void)RCC->APB1ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB2 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB2(mask, lp) { \ + RCC->APB2ENR |= (mask); \ + (void)RCC->APB2ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + (void)RCC->APB2ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CANEN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CANEN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CANRST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name DMA peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetDMA1() + +/** + * @brief Enables the DMA2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetDMA2() +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @brief Resets the SPI1 peripheral. + * + * @api + */ +#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) + +/** + * @brief Enables the SPI2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @brief Resets the TIM1 peripheral. + * + * @api + */ +#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) + +/** + * @brief Enables the TIM2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) + +/** + * @brief Enables the USART2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the USART4 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_USART4EN, lp) + +/** + * @brief Disables the USART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_USART4EN) + +/** + * @brief Resets the USART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_USART4RST) + +/** + * @brief Enables the USART5 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_USART5EN, lp) + +/** + * @brief Disables the USART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_USART5EN) + +/** + * @brief Resets the USART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_USART5RST) + +/** + * @brief Enables the USART6 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp) + +/** + * @brief Disables the USART6 peripheral clock. + * + * @api + */ +#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) + +/** + * @brief Resets the USART6 peripheral. + * + * @api + */ +#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) + +/** + * @brief Enables the UART7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART7(lp) rccEnableAPB2(RCC_APB2ENR_USART7EN, lp) + +/** + * @brief Disables the UART7 peripheral clock. + * + * @api + */ +#define rccDisableUART7() rccDisableAPB2(RCC_APB2ENR_USART7EN) + +/** + * @brief Resets the UART7 peripheral. + * + * @api + */ +#define rccResetUART7() rccResetAPB2(RCC_APB2RSTR_USART7RST) + +/** + * @brief Enables the UART8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART8(lp) rccEnableAPB2(RCC_APB2ENR_USART8EN, lp) + +/** + * @brief Disables the UART8 peripheral clock. + * + * @api + */ +#define rccDisableUART8() rccDisableAPB2(RCC_APB2ENR_USART8EN) + +/** + * @brief Resets the UART8 peripheral. + * + * @api + */ +#define rccResetUART8() rccResetAPB2(RCC_APB2RSTR_USART8RST) +/** @} */ + +/** + * @name USB peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/** + * @name CRC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST) +/** @} */ + +/** + * @name WWDG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the WWDG peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableWWDG(lp) rccEnableAPB1(RCC_APB1ENR_WWDGEN, lp) + +/** + * @brief Disables the WWDG peripheral clock. + * + * @api + */ +#define rccDisableWWDG() rccDisableAPB1(RCC_APB1ENR_WWDGEN) + +/** + * @brief Resets the WWDG peripheral. + * + * @api + */ +#define rccResetWWDG() rccResetAPB1(RCC_APB1RSTR_WWDGRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F0xx/stm32_registry.h b/os/hal/ports/STM32/STM32F0xx/stm32_registry.h index f658daa30f..2c97ab4a72 100644 --- a/os/hal/ports/STM32/STM32F0xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32F0xx/stm32_registry.h @@ -1,2222 +1,2222 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_registry.h - * @brief STM32F0xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -#if !defined(STM32F0XX) || defined(__DOXYGEN__) -#define STM32F0XX -#endif - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F0xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 FALSE - -/*===========================================================================*/ -/* STM32F030x4, STM32F030x6, STM32F030x8, STM32F030xC. */ -/*===========================================================================*/ -#if defined(STM32F030x4) || defined(STM32F030x6) || \ - defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) - -/* Common identifier of all STM32F030 devices.*/ -#define STM32F030 - -/* RCC attributes. */ -#define STM32_HAS_HSI48 FALSE -#if defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_HSI_PREDIV TRUE -#else -#define STM32_HAS_HSI_PREDIV FALSE -#endif -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000011 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#if defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_DMA_SUPPORTS_CSELR TRUE -#else -#define STM32_DMA_SUPPORTS_CSELR FALSE -#endif -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 20 -#define STM32_EXTI_IMR1_MASK 0xFFF50000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#if !defined(STM32F030x4) && !defined(STM32F030x6) -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#else -#define STM32_HAS_GPIOC FALSE -#define STM32_HAS_GPIOD FALSE -#endif -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C1_RX_DMA_CHN 0x00000200 -#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C1_TX_DMA_CHN 0x00000020 - -#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00020000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00002000 -#else -#define STM32_HAS_I2C2 FALSE -#endif - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#if defined (STM32F030xC) -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#else -#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE -#endif -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000030 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000300 - -#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_SPI2_RX_DMA_CHN 0x00003000 -#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_SPI2_TX_DMA_CHN 0x00030000 -#else -#define STM32_HAS_SPI2 FALSE -#endif - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 -#else -#define STM32_HAS_TIM6 FALSE -#endif - -#if defined(STM32F030xC) -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 -#else -#define STM32_HAS_TIM7 FALSE -#endif - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 -#else -#define STM32_HAS_TIM15 FALSE -#endif - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM2 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00080808 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00008080 - -#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART2_RX_DMA_CHN 0x00090909 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART2_TX_DMA_CHN 0x00009090 -#else -#define STM32_HAS_USART2 FALSE -#endif - -#if defined(STM32F030xC) || defined(__DOXYGEN__) -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART3_RX_DMA_CHN 0x000A0A0A -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x0000A0A0 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_UART4_RX_DMA_CHN 0x000B0B0B -#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_UART4_TX_DMA_CHN 0x0000B0B0 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_UART5_RX_DMA_CHN 0x000C0C0C -#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_UART5_TX_DMA_CHN 0x0000C0C0 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART6_RX_DMA_CHN 0x000D0D0D -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART6_TX_DMA_CHN 0x0000D0D0 - -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE -#else -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE -#endif - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -/*===========================================================================*/ -/* STM32F031x6, STM32F038xx. */ -/*===========================================================================*/ -#elif defined(STM32F031x6) || defined(STM32F038xx) - -/* RCC attributes. */ -#define STM32_HAS_HSI48 FALSE -#define STM32_HAS_HSI_PREDIV FALSE -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x0FF40000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C1_RX_DMA_CHN 0x00000000 -#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000000 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00000000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART2 FALSE -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32F042x6. */ -/*===========================================================================*/ -#elif defined(STM32F042x6) - -/* RCC attributes. */ -#define STM32_HAS_HSI48 TRUE -#define STM32_HAS_HSI_PREDIV TRUE -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x7FF40000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C1_RX_DMA_CHN 0x00000000 -#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000000 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00000000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00000000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_USART2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32F048xx. */ -/*===========================================================================*/ -#elif defined(STM32F048xx) - -/* RCC attributes. */ -#define STM32_HAS_HSI48 TRUE -#define STM32_HAS_HSI_PREDIV TRUE -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x7FF40000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C1_RX_DMA_CHN 0x00000000 -#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000000 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_SPI2_RX_DMA_CHN 0x00000000 -#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_SPI2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00000000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00000000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_USART2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR TRUE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32F051x8, STM32F058xx. */ -/*===========================================================================*/ -#elif defined(STM32F051x8) || defined(STM32F058xx) - -/* RCC attributes. */ -#define STM32_HAS_HSI48 FALSE -#define STM32_HAS_HSI_PREDIV FALSE -#define STM32_HAS_MCO_PREDIV FALSE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_DAC1_CH1_DMA_CHN 0x00000000 - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 - -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x0F940000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C1_RX_DMA_CHN 0x00000000 -#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00000000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000000 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_SPI2_RX_DMA_CHN 0x00000000 -#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_SPI2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00000000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00000000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_USART2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32F070x6, STM32F070xB. */ -/*===========================================================================*/ -#elif defined(STM32F070x6) || defined(STM32F070xB) - -/* Common identifier of all STM32F070 devices.*/ -#define STM32F070 - -/* RCC attributes. */ -#define STM32_HAS_HSI48 FALSE -#define STM32_HAS_HSI_PREDIV TRUE -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x7F840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#if defined(STM32F070x6) -#define STM32_HAS_GPIOD FALSE -#else -#define STM32_HAS_GPIOD TRUE -#endif -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C1_RX_DMA_CHN 0x00000000 -#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00000000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#if defined (STM32F070xB) -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#else -#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE -#endif -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000000 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_SPI2_RX_DMA_CHN 0x00000000 -#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_SPI2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM2 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00000000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00000000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_USART2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_USART3_RX_DMA_CHN 0x00000000 -#define STM32_USART3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_USART3_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK 0 -#define STM32_UART4_RX_DMA_CHN 0x00000000 -#define STM32_UART4_TX_DMA_MSK 0 -#define STM32_UART4_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -/*===========================================================================*/ -/* STM32F071xB, STM32F072xB, STM32F078xx. */ -/*===========================================================================*/ -#elif defined(STM32F071xB) || defined(STM32F072xB) || \ - defined(STM32F078xx) - -/* RCC attributes. */ -#define STM32_HAS_HSI48 TRUE -#define STM32_HAS_HSI_PREDIV TRUE -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#if defined(STM32F072xB) -#define STM32_HAS_CAN1 TRUE -#define STM32_CAN_MAX_FILTERS 14 -#else -#define STM32_HAS_CAN1 FALSE -#endif -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_DAC1_CH1_DMA_CHN 0x00000000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_DAC1_CH2_DMA_CHN 0x00000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH4567_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x7F840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x00000000 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00000000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_SPI1_RX_DMA_CHN 0x00000000 -#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_RX_DMA_CHN 0x00000000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00000000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00000000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_USART3_RX_DMA_CHN 0x00000000 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_USART3_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART4_RX_DMA_CHN 0x00000000 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART4_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#if defined(STM32F072xB) || defined(STM32F078xx) -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR TRUE -#else -#define STM32_HAS_USB FALSE -#endif -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32F091xC, STM32F098xx. */ -/*===========================================================================*/ -#elif defined(STM32F091xC) || defined(STM32F098xx) - -/* RCC attributes. */ -#define STM32_HAS_HSI48 TRUE -#define STM32_HAS_HSI_PREDIV TRUE -#define STM32_HAS_MCO_PREDIV TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER FALSE -#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_ADC1_DMA_CHN 0x00100011 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_DAC1_CH1_DMA_CHN 0x00000100 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_DAC1_CH2_DMA_CHN 0x00001000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 5 - -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA12_CH23_CH12_HANDLER Vector68 -#define STM32_DMA12_CH4567_CH345_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA12_CH23_CH12_NUMBER 10 -#define STM32_DMA12_CH4567_CH345_NUMBER 11 - -#define STM32_DMA1_CH2_NUMBER STM32_DMA12_CH23_CH12_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA12_CH23_CH12_NUMBER -#define STM32_DMA2_CH1_NUMBER STM32_DMA12_CH23_CH12_NUMBER -#define STM32_DMA2_CH2_NUMBER STM32_DMA12_CH23_CH12_NUMBER -#define STM32_DMA1_CH2_CMASK 0x00000186U -#define STM32_DMA1_CH3_CMASK 0x00000186U -#define STM32_DMA2_CH1_CMASK 0x00000186U -#define STM32_DMA2_CH2_CMASK 0x00000186U - -#define STM32_DMA1_CH4_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA2_CH3_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA2_CH4_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA2_CH5_NUMBER STM32_DMA12_CH4567_CH345_NUMBER -#define STM32_DMA1_CH4_CMASK 0x00000E78U -#define STM32_DMA1_CH5_CMASK 0x00000E78U -#define STM32_DMA1_CH6_CMASK 0x00000E78U -#define STM32_DMA1_CH7_CMASK 0x00000E78U -#define STM32_DMA2_CH3_CMASK 0x00000E78U -#define STM32_DMA2_CH4_CMASK 0x00000E78U -#define STM32_DMA2_CH5_CMASK 0x00000E78U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 32 -#define STM32_EXTI_IMR1_MASK 0x7F840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x02000200 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00200020 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_I2C2_RX_DMA_CHN 0x00020020 -#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_I2C2_TX_DMA_CHN 0x00002002 - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 0 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_RX_DMA_CHN 0x00000330 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI1_TX_DMA_CHN 0x00003300 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_RX_DMA_CHN 0x00303000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI2_TX_DMA_CHN 0x03030000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_USART1_RX_DMA_CHN 0x00880888 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_TX_DMA_CHN 0x08088088 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_USART2_RX_DMA_CHN 0x00990999 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART2_TX_DMA_CHN 0x09099099 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_USART3_RX_DMA_CHN 0x00AA0AAA -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART3_TX_DMA_CHN 0x0A0AA0AA - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_UART4_RX_DMA_CHN 0x00BB0BBB -#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_UART4_TX_DMA_CHN 0x0B0BB0BB - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_UART5_RX_DMA_CHN 0x00CC0CCC -#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_UART5_TX_DMA_CHN 0x0C0CC0CC - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_USART6_RX_DMA_CHN 0x00DD0DDD -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART6_TX_DMA_CHN 0x0D0DD0DD - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_UART7_RX_DMA_CHN 0x00EE0EEE -#define STM32_UART7_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_UART7_TX_DMA_CHN 0x0E0EE0EE - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_UART8_RX_DMA_CHN 0x00FF0FFF -#define STM32_UART8_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_UART8_TX_DMA_CHN 0x0F0FF0FF - -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#else -#error "STM32F0xx device not specified" -#endif - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_registry.h + * @brief STM32F0xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +#if !defined(STM32F0XX) || defined(__DOXYGEN__) +#define STM32F0XX +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F0xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 FALSE + +/*===========================================================================*/ +/* STM32F030x4, STM32F030x6, STM32F030x8, STM32F030xC. */ +/*===========================================================================*/ +#if defined(STM32F030x4) || defined(STM32F030x6) || \ + defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) + +/* Common identifier of all STM32F030 devices.*/ +#define STM32F030 + +/* RCC attributes. */ +#define STM32_HAS_HSI48 FALSE +#if defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_HSI_PREDIV TRUE +#else +#define STM32_HAS_HSI_PREDIV FALSE +#endif +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000011 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#if defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_DMA_SUPPORTS_CSELR TRUE +#else +#define STM32_DMA_SUPPORTS_CSELR FALSE +#endif +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 20 +#define STM32_EXTI_IMR1_MASK 0xFFF50000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#if !defined(STM32F030x4) && !defined(STM32F030x6) +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#else +#define STM32_HAS_GPIOC FALSE +#define STM32_HAS_GPIOD FALSE +#endif +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C1_RX_DMA_CHN 0x00000200 +#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C1_TX_DMA_CHN 0x00000020 + +#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00020000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00002000 +#else +#define STM32_HAS_I2C2 FALSE +#endif + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#if defined (STM32F030xC) +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#else +#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE +#endif +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000030 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000300 + +#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_SPI2_RX_DMA_CHN 0x00003000 +#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_SPI2_TX_DMA_CHN 0x00030000 +#else +#define STM32_HAS_SPI2 FALSE +#endif + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 +#else +#define STM32_HAS_TIM6 FALSE +#endif + +#if defined(STM32F030xC) +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 +#else +#define STM32_HAS_TIM7 FALSE +#endif + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 +#else +#define STM32_HAS_TIM15 FALSE +#endif + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM2 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00080808 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00008080 + +#if defined(STM32F030x8) || defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART2_RX_DMA_CHN 0x00090909 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART2_TX_DMA_CHN 0x00009090 +#else +#define STM32_HAS_USART2 FALSE +#endif + +#if defined(STM32F030xC) || defined(__DOXYGEN__) +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART3_RX_DMA_CHN 0x000A0A0A +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x0000A0A0 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_UART4_RX_DMA_CHN 0x000B0B0B +#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_UART4_TX_DMA_CHN 0x0000B0B0 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_UART5_RX_DMA_CHN 0x000C0C0C +#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_UART5_TX_DMA_CHN 0x0000C0C0 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART6_RX_DMA_CHN 0x000D0D0D +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART6_TX_DMA_CHN 0x0000D0D0 + +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE +#else +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE +#endif + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +/*===========================================================================*/ +/* STM32F031x6, STM32F038xx. */ +/*===========================================================================*/ +#elif defined(STM32F031x6) || defined(STM32F038xx) + +/* RCC attributes. */ +#define STM32_HAS_HSI48 FALSE +#define STM32_HAS_HSI_PREDIV FALSE +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x0FF40000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C1_RX_DMA_CHN 0x00000000 +#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000000 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00000000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART2 FALSE +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32F042x6. */ +/*===========================================================================*/ +#elif defined(STM32F042x6) + +/* RCC attributes. */ +#define STM32_HAS_HSI48 TRUE +#define STM32_HAS_HSI_PREDIV TRUE +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x7FF40000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C1_RX_DMA_CHN 0x00000000 +#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000000 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00000000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00000000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_USART2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32F048xx. */ +/*===========================================================================*/ +#elif defined(STM32F048xx) + +/* RCC attributes. */ +#define STM32_HAS_HSI48 TRUE +#define STM32_HAS_HSI_PREDIV TRUE +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x7FF40000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C1_RX_DMA_CHN 0x00000000 +#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000000 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_SPI2_RX_DMA_CHN 0x00000000 +#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_SPI2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00000000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00000000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_USART2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR TRUE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32F051x8, STM32F058xx. */ +/*===========================================================================*/ +#elif defined(STM32F051x8) || defined(STM32F058xx) + +/* RCC attributes. */ +#define STM32_HAS_HSI48 FALSE +#define STM32_HAS_HSI_PREDIV FALSE +#define STM32_HAS_MCO_PREDIV FALSE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_DAC1_CH1_DMA_CHN 0x00000000 + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 + +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x0F940000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C1_RX_DMA_CHN 0x00000000 +#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00000000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000000 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_SPI2_RX_DMA_CHN 0x00000000 +#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_SPI2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00000000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00000000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_USART2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32F070x6, STM32F070xB. */ +/*===========================================================================*/ +#elif defined(STM32F070x6) || defined(STM32F070xB) + +/* Common identifier of all STM32F070 devices.*/ +#define STM32F070 + +/* RCC attributes. */ +#define STM32_HAS_HSI48 FALSE +#define STM32_HAS_HSI_PREDIV TRUE +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x7F840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#if defined(STM32F070x6) +#define STM32_HAS_GPIOD FALSE +#else +#define STM32_HAS_GPIOD TRUE +#endif +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C1_RX_DMA_CHN 0x00000000 +#define STM32_I2C1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00000000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#if defined (STM32F070xB) +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#else +#define STM32_RTC_HAS_PERIODIC_WAKEUPS FALSE +#endif +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000000 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_SPI2_RX_DMA_CHN 0x00000000 +#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_SPI2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM2 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00000000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00000000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_USART2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_USART3_RX_DMA_CHN 0x00000000 +#define STM32_USART3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_USART3_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK 0 +#define STM32_UART4_RX_DMA_CHN 0x00000000 +#define STM32_UART4_TX_DMA_MSK 0 +#define STM32_UART4_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +/*===========================================================================*/ +/* STM32F071xB, STM32F072xB, STM32F078xx. */ +/*===========================================================================*/ +#elif defined(STM32F071xB) || defined(STM32F072xB) || \ + defined(STM32F078xx) + +/* RCC attributes. */ +#define STM32_HAS_HSI48 TRUE +#define STM32_HAS_HSI_PREDIV TRUE +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#if defined(STM32F072xB) +#define STM32_HAS_CAN1 TRUE +#define STM32_CAN_MAX_FILTERS 14 +#else +#define STM32_HAS_CAN1 FALSE +#endif +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_DAC1_CH1_DMA_CHN 0x00000000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_DAC1_CH2_DMA_CHN 0x00000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH4567_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x7F840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x00000000 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00000000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_SPI1_RX_DMA_CHN 0x00000000 +#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_RX_DMA_CHN 0x00000000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00000000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00000000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_USART3_RX_DMA_CHN 0x00000000 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_USART3_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART4_RX_DMA_CHN 0x00000000 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART4_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#if defined(STM32F072xB) || defined(STM32F078xx) +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR TRUE +#else +#define STM32_HAS_USB FALSE +#endif +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32F091xC, STM32F098xx. */ +/*===========================================================================*/ +#elif defined(STM32F091xC) || defined(STM32F098xx) + +/* RCC attributes. */ +#define STM32_HAS_HSI48 TRUE +#define STM32_HAS_HSI_PREDIV TRUE +#define STM32_HAS_MCO_PREDIV TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER FALSE +#define STM32_ADC_SUPPORTS_OVERSAMPLING FALSE +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_ADC1_DMA_CHN 0x00100011 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_DAC1_CH1_DMA_CHN 0x00000100 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_DAC1_CH2_DMA_CHN 0x00001000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 5 + +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA12_CH23_CH12_HANDLER Vector68 +#define STM32_DMA12_CH4567_CH345_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA12_CH23_CH12_NUMBER 10 +#define STM32_DMA12_CH4567_CH345_NUMBER 11 + +#define STM32_DMA1_CH2_NUMBER STM32_DMA12_CH23_CH12_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA12_CH23_CH12_NUMBER +#define STM32_DMA2_CH1_NUMBER STM32_DMA12_CH23_CH12_NUMBER +#define STM32_DMA2_CH2_NUMBER STM32_DMA12_CH23_CH12_NUMBER +#define STM32_DMA1_CH2_CMASK 0x00000186U +#define STM32_DMA1_CH3_CMASK 0x00000186U +#define STM32_DMA2_CH1_CMASK 0x00000186U +#define STM32_DMA2_CH2_CMASK 0x00000186U + +#define STM32_DMA1_CH4_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA2_CH3_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA2_CH4_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA2_CH5_NUMBER STM32_DMA12_CH4567_CH345_NUMBER +#define STM32_DMA1_CH4_CMASK 0x00000E78U +#define STM32_DMA1_CH5_CMASK 0x00000E78U +#define STM32_DMA1_CH6_CMASK 0x00000E78U +#define STM32_DMA1_CH7_CMASK 0x00000E78U +#define STM32_DMA2_CH3_CMASK 0x00000E78U +#define STM32_DMA2_CH4_CMASK 0x00000E78U +#define STM32_DMA2_CH5_CMASK 0x00000E78U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 32 +#define STM32_EXTI_IMR1_MASK 0x7F840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x02000200 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00200020 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_I2C2_RX_DMA_CHN 0x00020020 +#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_I2C2_TX_DMA_CHN 0x00002002 + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 0 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_IRQ_PRIORITY) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_RX_DMA_CHN 0x00000330 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI1_TX_DMA_CHN 0x00003300 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_RX_DMA_CHN 0x00303000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI2_TX_DMA_CHN 0x03030000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_USART1_RX_DMA_CHN 0x00880888 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_TX_DMA_CHN 0x08088088 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_USART2_RX_DMA_CHN 0x00990999 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART2_TX_DMA_CHN 0x09099099 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_USART3_RX_DMA_CHN 0x00AA0AAA +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART3_TX_DMA_CHN 0x0A0AA0AA + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_UART4_RX_DMA_CHN 0x00BB0BBB +#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_UART4_TX_DMA_CHN 0x0B0BB0BB + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_UART5_RX_DMA_CHN 0x00CC0CCC +#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_UART5_TX_DMA_CHN 0x0C0CC0CC + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_USART6_RX_DMA_CHN 0x00DD0DDD +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART6_TX_DMA_CHN 0x0D0DD0DD + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_UART7_RX_DMA_CHN 0x00EE0EEE +#define STM32_UART7_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_UART7_TX_DMA_CHN 0x0E0EE0EE + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_UART8_RX_DMA_CHN 0x00FF0FFF +#define STM32_UART8_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_UART8_TX_DMA_CHN 0x0F0FF0FF + +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#else +#error "STM32F0xx device not specified" +#endif + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c b/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c index 9f29a911c2..ac44ea553c 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c +++ b/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c @@ -1,235 +1,235 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/hal_adc_lld.c - * @brief STM32F1xx ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared 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) != 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 { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = NULL; - ADCD1.dmamode = STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_TEIE; - - /* Temporary activation.*/ - rccEnableADC1(true); - ADC1->CR1 = 0; - ADC1->CR2 = ADC_CR2_ADON; - - /* Reset calibration just to be safe.*/ - ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; - while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0) - ; - - /* Calibration.*/ - ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL; - while ((ADC1->CR2 & ADC_CR2_CAL) != 0) - ; - - /* Return the ADC in low power mode.*/ - ADC1->CR2 = 0; - rccDisableADC1(); -#endif -} - -/** - * @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) { - adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(1, 1), - STM32_ADC_ADC1_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - rccEnableADC1(true); - } -#endif - - /* ADC setup, the calibration procedure has already been performed - during initialization.*/ - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - } -} - -/** - * @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) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - ADC1->CR1 = 0; - ADC1->CR2 = 0; - - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - - rccDisableADC1(); - } -#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, cr2; - const ADCConversionGroup *grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup.*/ - adcp->adc->CR1 = grpp->cr1 | ADC_CR1_SCAN; - cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_ADON; - if ((cr2 & (ADC_CR2_EXTTRIG | ADC_CR2_JEXTTRIG)) == 0) - cr2 |= ADC_CR2_CONT; - adcp->adc->CR2 = grpp->cr2 | cr2; - 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 start by writing ADC_CR2_ADON a second time.*/ - adcp->adc->CR2 = cr2; -} - -/** - * @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->CR2 = 0; -} - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/hal_adc_lld.c + * @brief STM32F1xx ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared 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) != 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 { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = NULL; + ADCD1.dmamode = STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_TEIE; + + /* Temporary activation.*/ + rccEnableADC1(true); + ADC1->CR1 = 0; + ADC1->CR2 = ADC_CR2_ADON; + + /* Reset calibration just to be safe.*/ + ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; + while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0) + ; + + /* Calibration.*/ + ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL; + while ((ADC1->CR2 & ADC_CR2_CAL) != 0) + ; + + /* Return the ADC in low power mode.*/ + ADC1->CR2 = 0; + rccDisableADC1(); +#endif +} + +/** + * @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) { + adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(1, 1), + STM32_ADC_ADC1_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + rccEnableADC1(true); + } +#endif + + /* ADC setup, the calibration procedure has already been performed + during initialization.*/ + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + } +} + +/** + * @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) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + ADC1->CR1 = 0; + ADC1->CR2 = 0; + + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + + rccDisableADC1(); + } +#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, cr2; + const ADCConversionGroup *grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup.*/ + adcp->adc->CR1 = grpp->cr1 | ADC_CR1_SCAN; + cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_ADON; + if ((cr2 & (ADC_CR2_EXTTRIG | ADC_CR2_JEXTTRIG)) == 0) + cr2 |= ADC_CR2_CONT; + adcp->adc->CR2 = grpp->cr2 | cr2; + 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 start by writing ADC_CR2_ADON a second time.*/ + adcp->adc->CR2 = cr2; +} + +/** + * @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->CR2 = 0; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.h b/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.h index 38772cab9a..6060ad423e 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.h +++ b/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.h @@ -1,284 +1,284 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/hal_adc_lld.h - * @brief STM32F1xx ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Triggers selection - * @{ - */ -#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @brief Trigger source. */ -#define ADC_CR2_EXTSEL_SWSTART (7 << 17) /**< @brief Software trigger. */ -/** @} */ - -/** - * @name Available analog channels - * @{ - */ -#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ -#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ -#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ -#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ -#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ -#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ -#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ -#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ -#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ -#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ -#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ -#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ -#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ -#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ -#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ -#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ -#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/ -#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */ -#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */ -#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */ -#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */ -#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */ -#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */ -#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */ -#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#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 ADC1 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_IRQ_PRIORITY 5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC1 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -typedef uint16_t adcsample_t; - -/** - * @brief Channels number in a conversion group. - */ -typedef uint16_t adc_channels_num_t; - -/** - * @brief Possible ADC failure causes. - * @note Error codes are architecture dependent and should not relied - * upon. - */ -typedef enum { - ADC_ERR_DMAFAILURE = 0 /**< DMA operations failure. */ -} adcerror_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_configuration_group_fields \ - /* 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; \ - /* 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; \ - /* ADC SMPR1 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 10...17.*/ \ - uint32_t smpr1; \ - /* ADC SMPR2 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 0...9.*/ \ - uint32_t smpr2; \ - /* ADC SQR1 register initialization data. \ - NOTE: Conversion group sequence 13...16 + sequence length.*/ \ - uint32_t sqr1; \ - /* ADC SQR2 register initialization data. \ - NOTE: Conversion group sequence 7...12.*/ \ - uint32_t sqr2; \ - /* ADC SQR3 register initialization data. \ - NOTE: Conversion group sequence 1...6.*/ \ - uint32_t sqr3 - -/** - * @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. */ -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/hal_adc_lld.h + * @brief STM32F1xx ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Triggers selection + * @{ + */ +#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @brief Trigger source. */ +#define ADC_CR2_EXTSEL_SWSTART (7 << 17) /**< @brief Software trigger. */ +/** @} */ + +/** + * @name Available analog channels + * @{ + */ +#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ +#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ +#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ +#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ +#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ +#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ +#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ +#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ +#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ +#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ +#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ +#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ +#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ +#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ +#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ +#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ +#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/ +#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */ +#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */ +#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */ +#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */ +#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */ +#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */ +#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */ +#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#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 ADC1 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_IRQ_PRIORITY 5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC1 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +typedef uint16_t adcsample_t; + +/** + * @brief Channels number in a conversion group. + */ +typedef uint16_t adc_channels_num_t; + +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0 /**< DMA operations failure. */ +} adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_configuration_group_fields \ + /* 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; \ + /* 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; \ + /* ADC SMPR1 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 10...17.*/ \ + uint32_t smpr1; \ + /* ADC SMPR2 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 0...9.*/ \ + uint32_t smpr2; \ + /* ADC SQR1 register initialization data. \ + NOTE: Conversion group sequence 13...16 + sequence length.*/ \ + uint32_t sqr1; \ + /* ADC SQR2 register initialization data. \ + NOTE: Conversion group sequence 7...12.*/ \ + uint32_t sqr2; \ + /* ADC SQR3 register initialization data. \ + NOTE: Conversion group sequence 1...6.*/ \ + uint32_t sqr3 + +/** + * @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. */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.c b/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.c index 3032085fa2..a4885f097d 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.c +++ b/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.c @@ -1,489 +1,489 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_efl_lld.c - * @brief STM32F1xx Embedded Flash subsystem low level driver source. - * - * @addtogroup HAL_EFL - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define STM32_FLASH_LINE_SIZE 2U -#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief EFL1 driver identifier. - */ -EFlashDriver EFLD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const flash_descriptor_t efl_lld_descriptor = { - .attributes = FLASH_ATTR_ERASED_IS_ONE | - FLASH_ATTR_MEMORY_MAPPED, - .page_size = STM32_FLASH_LINE_SIZE, - .sectors_count = STM32_FLASH_NUMBER_OF_BANKS * - STM32_FLASH_SECTORS_PER_BANK, - .sectors = NULL, - .sectors_size = STM32_FLASH_SECTOR_SIZE, - .address = (uint8_t *)FLASH_BASE, - .size = STM32_FLASH_NUMBER_OF_BANKS * - STM32_FLASH_SECTORS_PER_BANK * - STM32_FLASH_SECTOR_SIZE -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static inline void stm32_flash_lock(EFlashDriver *eflp) { - - eflp->flash->CR |= FLASH_CR_LOCK; -} - -static inline void stm32_flash_unlock(EFlashDriver *eflp) { - - eflp->flash->KEYR |= FLASH_KEY1; - eflp->flash->KEYR |= FLASH_KEY2; -} - -static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) { - - eflp->flash->CR |= FLASH_CR_PG; -} - -static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) { - - eflp->flash->CR &= ~FLASH_CR_PG; -} - -static inline void stm32_flash_clear_status(EFlashDriver *eflp) { - - eflp->flash->SR = 0x0000001FU; -} - -static inline uint32_t stm32_flash_is_busy(EFlashDriver *eflp) { - - return (eflp->flash->SR & FLASH_SR_BSY); -} - -static inline void stm32_flash_wait_busy(EFlashDriver *eflp) { - - /* Wait for busy bit clear.*/ - while (stm32_flash_is_busy(eflp) != 0U) { - } -} - -static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) { - uint32_t sr = eflp->flash->SR; - - /* Clearing error conditions.*/ - eflp->flash->SR = sr & 0x0000001FU; - - /* Decoding relevant errors.*/ - if ((sr & FLASH_SR_WRPRTERR) != 0U) { - return FLASH_ERROR_HW_FAILURE; - } - - if ((sr & FLASH_SR_PGERR) != 0U) { - return FLASH_ERROR_PROGRAM; /* There is no error on erase.*/ - } - - return FLASH_NO_ERROR; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level Embedded Flash driver initialization. - * - * @notapi - */ -void efl_lld_init(void) { - - /* Driver initialization.*/ - eflObjectInit(&EFLD1); - EFLD1.flash = FLASH; -} - -/** - * @brief Configures and activates the Embedded Flash peripheral. - * - * @param[in] eflp pointer to a @p EFlashDriver structure - * - * @notapi - */ -void efl_lld_start(EFlashDriver *eflp) { - - stm32_flash_unlock(eflp); - FLASH->CR = 0x00000000U; -} - -/** - * @brief Deactivates the Embedded Flash peripheral. - * - * @param[in] eflp pointer to a @p EFlashDriver structure - * - * @notapi - */ -void efl_lld_stop(EFlashDriver *eflp) { - - stm32_flash_lock(eflp); -} - -/** - * @brief Gets the flash descriptor structure. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @return A flash device descriptor. - * - * @notapi - */ -const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { - - (void)instance; - - return &efl_lld_descriptor; -} - -/** - * @brief Read operation. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] offset flash offset - * @param[in] n number of bytes to be read - * @param[out] rp pointer to the data buffer - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_READ if the read operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_read(void *instance, flash_offset_t offset, - size_t n, uint8_t *rp) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err = FLASH_NO_ERROR; - - osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); - osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No reading while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_READY state while the operation is performed.*/ - devp->state = FLASH_READ; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Actual read implementation.*/ - memcpy((void *)rp, (const void *)efl_lld_descriptor.address + offset, n); - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -/** - * @brief Program operation. - * @note It is only possible to write erased pages once except - * when writing all zeroes. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] offset flash offset - * @param[in] n number of bytes to be programmed - * @param[in] pp pointer to the data buffer - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_PROGRAM if the program operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_program(void *instance, flash_offset_t offset, - size_t n, const uint8_t *pp) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err = FLASH_NO_ERROR; - - osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); - osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); - - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No programming while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_PGM; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Enabling PGM mode in the controller.*/ - stm32_flash_enable_pgm(devp); - - /* Actual program implementation.*/ - while (n > 0U) { - volatile uint16_t *address; - - union { - uint16_t hw[STM32_FLASH_LINE_SIZE / sizeof (uint16_t)]; - uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)]; - } line; - - /* Unwritten bytes are initialized to all ones.*/ - line.hw[0] = 0xFFFFU; - - /* Programming address aligned to flash lines.*/ - address = (volatile uint16_t *)(efl_lld_descriptor.address + - (offset & ~STM32_FLASH_LINE_MASK)); - - /* Copying data inside the prepared line.*/ - do { - line.b[offset & STM32_FLASH_LINE_MASK] = *pp; - offset++; - n--; - pp++; - } - while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U)); - - /* Programming line.*/ - address[0] = line.hw[0]; - stm32_flash_wait_busy(devp); - - err = stm32_flash_check_errors(devp); - if (err != FLASH_NO_ERROR) { - break; - } - /* Check for flash error.*/ - if (address[0] != line.hw[0]) { - err = FLASH_ERROR_PROGRAM; - break; - } - } - - /* Disabling PGM mode in the controller.*/ - stm32_flash_disable_pgm(devp); - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -/** - * @brief Starts a whole-device erase operation. - * @note This function does nothing, the flash memory is where the program - * is running on. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_start_erase_all(void *instance) { - (void) instance; - - return FLASH_ERROR_UNIMPLEMENTED; -} - -/** - * @brief Starts an sector erase operation. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] sector sector to be erased - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_start_erase_sector(void *instance, - flash_sector_t sector) { - EFlashDriver *devp = (EFlashDriver *)instance; - - osalDbgCheck(instance != NULL); - osalDbgCheck(sector < efl_lld_descriptor.sectors_count); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No erasing while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_ERASE; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Enable page erase.*/ - devp->flash->CR |= FLASH_CR_PER; - - /* Set the page.*/ - devp->flash->AR = (uint32_t)(efl_lld_descriptor.address + - flashGetSectorOffset(getBaseFlash(devp), sector)); - - /* Start the erase.*/ - devp->flash->CR |= FLASH_CR_STRT; - - return FLASH_NO_ERROR; -} - -/** - * @brief Queries the driver for erase operation progress. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[out] wait_time recommended time, in milliseconds, that - * should be spent before calling this - * function again, can be @p NULL - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_ERASE if the erase operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @api - */ -flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err; - - /* If there is an erase in progress then the device must be checked.*/ - if (devp->state == FLASH_ERASE) { - - /* Checking for operation in progress.*/ - if (stm32_flash_is_busy(devp) == 0U) { - - /* Disabling the various erase control bits.*/ - devp->flash->CR &= ~(FLASH_CR_OPTER | FLASH_CR_OPTPG | - FLASH_CR_MER | FLASH_CR_PER); - - /* Back to ready state.*/ - devp->state = FLASH_READY; - - err = FLASH_NO_ERROR; - } - else { - /* Recommended time before polling again, this is a simplified - implementation.*/ - if (wait_time != NULL) { - *wait_time = (uint32_t)STM32_FLASH_WAIT_TIME_MS; - } - - err = FLASH_BUSY_ERASING; - } - } - else { - err = FLASH_NO_ERROR; - } - - return err; -} - -/** - * @brief Returns the erase state of a sector. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] sector sector to be verified - * @return An error code. - * @retval FLASH_NO_ERROR if the sector is erased. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_VERIFY if the verify operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { - EFlashDriver *devp = (EFlashDriver *)instance; - uint32_t *address; - flash_error_t err = FLASH_NO_ERROR; - unsigned i; - - osalDbgCheck(instance != NULL); - osalDbgCheck(sector < efl_lld_descriptor.sectors_count); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No verifying while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* Address of the sector.*/ - address = (uint32_t *)(efl_lld_descriptor.address + - flashGetSectorOffset(getBaseFlash(devp), sector)); - - /* FLASH_READY state while the operation is performed.*/ - devp->state = FLASH_READ; - - /* Scanning the sector space.*/ - for (i = 0U; i < STM32_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) { - if (*address != 0xFFFFFFFFU) { - err = FLASH_ERROR_VERIFY; - break; - } - address++; - } - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -#endif /* HAL_USE_EFL == TRUE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_efl_lld.c + * @brief STM32F1xx Embedded Flash subsystem low level driver source. + * + * @addtogroup HAL_EFL + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define STM32_FLASH_LINE_SIZE 2U +#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EFL1 driver identifier. + */ +EFlashDriver EFLD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const flash_descriptor_t efl_lld_descriptor = { + .attributes = FLASH_ATTR_ERASED_IS_ONE | + FLASH_ATTR_MEMORY_MAPPED, + .page_size = STM32_FLASH_LINE_SIZE, + .sectors_count = STM32_FLASH_NUMBER_OF_BANKS * + STM32_FLASH_SECTORS_PER_BANK, + .sectors = NULL, + .sectors_size = STM32_FLASH_SECTOR_SIZE, + .address = (uint8_t *)FLASH_BASE, + .size = STM32_FLASH_NUMBER_OF_BANKS * + STM32_FLASH_SECTORS_PER_BANK * + STM32_FLASH_SECTOR_SIZE +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static inline void stm32_flash_lock(EFlashDriver *eflp) { + + eflp->flash->CR |= FLASH_CR_LOCK; +} + +static inline void stm32_flash_unlock(EFlashDriver *eflp) { + + eflp->flash->KEYR |= FLASH_KEY1; + eflp->flash->KEYR |= FLASH_KEY2; +} + +static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) { + + eflp->flash->CR |= FLASH_CR_PG; +} + +static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) { + + eflp->flash->CR &= ~FLASH_CR_PG; +} + +static inline void stm32_flash_clear_status(EFlashDriver *eflp) { + + eflp->flash->SR = 0x0000001FU; +} + +static inline uint32_t stm32_flash_is_busy(EFlashDriver *eflp) { + + return (eflp->flash->SR & FLASH_SR_BSY); +} + +static inline void stm32_flash_wait_busy(EFlashDriver *eflp) { + + /* Wait for busy bit clear.*/ + while (stm32_flash_is_busy(eflp) != 0U) { + } +} + +static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) { + uint32_t sr = eflp->flash->SR; + + /* Clearing error conditions.*/ + eflp->flash->SR = sr & 0x0000001FU; + + /* Decoding relevant errors.*/ + if ((sr & FLASH_SR_WRPRTERR) != 0U) { + return FLASH_ERROR_HW_FAILURE; + } + + if ((sr & FLASH_SR_PGERR) != 0U) { + return FLASH_ERROR_PROGRAM; /* There is no error on erase.*/ + } + + return FLASH_NO_ERROR; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level Embedded Flash driver initialization. + * + * @notapi + */ +void efl_lld_init(void) { + + /* Driver initialization.*/ + eflObjectInit(&EFLD1); + EFLD1.flash = FLASH; +} + +/** + * @brief Configures and activates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_start(EFlashDriver *eflp) { + + stm32_flash_unlock(eflp); + FLASH->CR = 0x00000000U; +} + +/** + * @brief Deactivates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_stop(EFlashDriver *eflp) { + + stm32_flash_lock(eflp); +} + +/** + * @brief Gets the flash descriptor structure. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @return A flash device descriptor. + * + * @notapi + */ +const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { + + (void)instance; + + return &efl_lld_descriptor; +} + +/** + * @brief Read operation. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] offset flash offset + * @param[in] n number of bytes to be read + * @param[out] rp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_READ if the read operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No reading while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_READY state while the operation is performed.*/ + devp->state = FLASH_READ; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Actual read implementation.*/ + memcpy((void *)rp, (const void *)efl_lld_descriptor.address + offset, n); + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +/** + * @brief Program operation. + * @note It is only possible to write erased pages once except + * when writing all zeroes. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] offset flash offset + * @param[in] n number of bytes to be programmed + * @param[in] pp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_PROGRAM if the program operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); + + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No programming while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_PGM; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Enabling PGM mode in the controller.*/ + stm32_flash_enable_pgm(devp); + + /* Actual program implementation.*/ + while (n > 0U) { + volatile uint16_t *address; + + union { + uint16_t hw[STM32_FLASH_LINE_SIZE / sizeof (uint16_t)]; + uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)]; + } line; + + /* Unwritten bytes are initialized to all ones.*/ + line.hw[0] = 0xFFFFU; + + /* Programming address aligned to flash lines.*/ + address = (volatile uint16_t *)(efl_lld_descriptor.address + + (offset & ~STM32_FLASH_LINE_MASK)); + + /* Copying data inside the prepared line.*/ + do { + line.b[offset & STM32_FLASH_LINE_MASK] = *pp; + offset++; + n--; + pp++; + } + while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U)); + + /* Programming line.*/ + address[0] = line.hw[0]; + stm32_flash_wait_busy(devp); + + err = stm32_flash_check_errors(devp); + if (err != FLASH_NO_ERROR) { + break; + } + /* Check for flash error.*/ + if (address[0] != line.hw[0]) { + err = FLASH_ERROR_PROGRAM; + break; + } + } + + /* Disabling PGM mode in the controller.*/ + stm32_flash_disable_pgm(devp); + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +/** + * @brief Starts a whole-device erase operation. + * @note This function does nothing, the flash memory is where the program + * is running on. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_all(void *instance) { + (void) instance; + + return FLASH_ERROR_UNIMPLEMENTED; +} + +/** + * @brief Starts an sector erase operation. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] sector sector to be erased + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < efl_lld_descriptor.sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No erasing while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_ERASE; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Enable page erase.*/ + devp->flash->CR |= FLASH_CR_PER; + + /* Set the page.*/ + devp->flash->AR = (uint32_t)(efl_lld_descriptor.address + + flashGetSectorOffset(getBaseFlash(devp), sector)); + + /* Start the erase.*/ + devp->flash->CR |= FLASH_CR_STRT; + + return FLASH_NO_ERROR; +} + +/** + * @brief Queries the driver for erase operation progress. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[out] wait_time recommended time, in milliseconds, that + * should be spent before calling this + * function again, can be @p NULL + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_ERASE if the erase operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @api + */ +flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err; + + /* If there is an erase in progress then the device must be checked.*/ + if (devp->state == FLASH_ERASE) { + + /* Checking for operation in progress.*/ + if (stm32_flash_is_busy(devp) == 0U) { + + /* Disabling the various erase control bits.*/ + devp->flash->CR &= ~(FLASH_CR_OPTER | FLASH_CR_OPTPG | + FLASH_CR_MER | FLASH_CR_PER); + + /* Back to ready state.*/ + devp->state = FLASH_READY; + + err = FLASH_NO_ERROR; + } + else { + /* Recommended time before polling again, this is a simplified + implementation.*/ + if (wait_time != NULL) { + *wait_time = (uint32_t)STM32_FLASH_WAIT_TIME_MS; + } + + err = FLASH_BUSY_ERASING; + } + } + else { + err = FLASH_NO_ERROR; + } + + return err; +} + +/** + * @brief Returns the erase state of a sector. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] sector sector to be verified + * @return An error code. + * @retval FLASH_NO_ERROR if the sector is erased. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_VERIFY if the verify operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + uint32_t *address; + flash_error_t err = FLASH_NO_ERROR; + unsigned i; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < efl_lld_descriptor.sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No verifying while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* Address of the sector.*/ + address = (uint32_t *)(efl_lld_descriptor.address + + flashGetSectorOffset(getBaseFlash(devp), sector)); + + /* FLASH_READY state while the operation is performed.*/ + devp->state = FLASH_READ; + + /* Scanning the sector space.*/ + for (i = 0U; i < STM32_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) { + if (*address != 0xFFFFFFFFU) { + err = FLASH_ERROR_VERIFY; + break; + } + address++; + } + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +#endif /* HAL_USE_EFL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.h b/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.h index 33708d24a9..8b3d741285 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.h +++ b/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.h @@ -1,120 +1,120 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_efl_lld.h - * @brief STM32F1xx Embedded Flash subsystem low level driver header. - * - * @addtogroup HAL_EFL - * @{ - */ - -#ifndef HAL_EFL_LLD_H -#define HAL_EFL_LLD_H - -#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name STM32F1xx configuration options - * @{ - */ -/** - * @brief Suggested wait time during erase operations polling. - */ -#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) -#define STM32_FLASH_WAIT_TIME_MS 1 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_FLASH_SECTOR_SIZE) -#error "STM32_FLASH_SECTOR_SIZE not defined in registry" -#endif - -#if !defined(STM32_FLASH_NUMBER_OF_BANKS) -#error "STM32_FLASH_NUMBER_OF_BANKS not defined in registry" -#endif - -#if !defined(STM32_FLASH_SECTORS_PER_BANK) -#error "STM32_FLASH_SECTORS_PER_BANK not defined in registry" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the embedded flash driver structure. - */ -#define efl_lld_driver_fields \ - /* Flash registers.*/ \ - FLASH_TypeDef *flash - -/** - * @brief Low level fields of the embedded flash configuration structure. - */ -#define efl_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern EFlashDriver EFLD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void efl_lld_init(void); - void efl_lld_start(EFlashDriver *eflp); - void efl_lld_stop(EFlashDriver *eflp); - const flash_descriptor_t *efl_lld_get_descriptor(void *instance); - flash_error_t efl_lld_read(void *instance, flash_offset_t offset, - size_t n, uint8_t *rp); - flash_error_t efl_lld_program(void *instance, flash_offset_t offset, - size_t n, const uint8_t *pp); - flash_error_t efl_lld_start_erase_all(void *instance); - flash_error_t efl_lld_start_erase_sector(void *instance, - flash_sector_t sector); - flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time); - flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EFL == TRUE */ - -#endif /* HAL_EFL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_efl_lld.h + * @brief STM32F1xx Embedded Flash subsystem low level driver header. + * + * @addtogroup HAL_EFL + * @{ + */ + +#ifndef HAL_EFL_LLD_H +#define HAL_EFL_LLD_H + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name STM32F1xx configuration options + * @{ + */ +/** + * @brief Suggested wait time during erase operations polling. + */ +#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) +#define STM32_FLASH_WAIT_TIME_MS 1 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_FLASH_SECTOR_SIZE) +#error "STM32_FLASH_SECTOR_SIZE not defined in registry" +#endif + +#if !defined(STM32_FLASH_NUMBER_OF_BANKS) +#error "STM32_FLASH_NUMBER_OF_BANKS not defined in registry" +#endif + +#if !defined(STM32_FLASH_SECTORS_PER_BANK) +#error "STM32_FLASH_SECTORS_PER_BANK not defined in registry" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the embedded flash driver structure. + */ +#define efl_lld_driver_fields \ + /* Flash registers.*/ \ + FLASH_TypeDef *flash + +/** + * @brief Low level fields of the embedded flash configuration structure. + */ +#define efl_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern EFlashDriver EFLD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void efl_lld_init(void); + void efl_lld_start(EFlashDriver *eflp); + void efl_lld_stop(EFlashDriver *eflp); + const flash_descriptor_t *efl_lld_get_descriptor(void *instance); + flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp); + flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp); + flash_error_t efl_lld_start_erase_all(void *instance); + flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector); + flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time); + flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EFL == TRUE */ + +#endif /* HAL_EFL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_lld.c b/os/hal/ports/STM32/STM32F1xx/hal_lld.c index 271abd2fb1..59d6d0a7d5 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32F1xx/hal_lld.c @@ -1,346 +1,347 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/hal_lld.c - * @brief STM32F1xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f10x.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - -#if HAL_USE_RTC - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif /* STM32_LSE_ENABLED */ - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* Prescaler value loaded in registers.*/ - rtc_lld_set_prescaler(); - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -#endif /* HAL_USE_RTC */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) -#if defined(STM32_DMA2_CH45_HANDLER) || defined(__DOXYGEN__) -/** - * @brief DMA2 streams 4 and 5 shared ISR. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_DMA2_CH45_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 4 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM4); - - /* Check on channel 5 of DMA2.*/ - dmaServeInterrupt(STM32_DMA2_STREAM5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* defined(STM32_DMA2_CH45_HANDLER) */ -#endif /* defined(STM32_DMA_REQUIRED) */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals.*/ - rccResetAPB1(0xFFFFFFFF); - rccResetAPB2(0xFFFFFFFF); - - /* PWR and BD clocks enabled.*/ - rccEnablePWRInterface(true); - rccEnableBKPInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32 clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -#if defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) || \ - defined(STM32F10X_MD) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ - defined(__DOXYGEN__) -/* - * Clocks initialization for all sub-families except CL. - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Waits until HSI is selected. */ - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC; - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Clock settings.*/ -#if STM32_HAS_USB - RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE | - STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | - STM32_HPRE; -#else - RCC->CFGR = STM32_MCOSEL | STM32_PLLMUL | STM32_PLLXTPRE | - STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | - STM32_HPRE; -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - /* Switches clock source.*/ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; /* Waits selection complete. */ -#endif - -#if !STM32_HSI_ENABLED - RCC->CR &= ~RCC_CR_HSION; -#endif -#endif /* !STM32_NO_INIT */ -} - -#elif defined(STM32F10X_CL) -/* - * Clocks initialization for the CL sub-family. - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. Clearing the register has to be postponed after HSI is the - new source.*/ - RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers finally cleared to reset values.*/ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - - /* Settings of various dividers and multipliers in CFGR2.*/ - RCC->CFGR2 = STM32_PLL3MUL | STM32_PLL2MUL | STM32_PREDIV2 | - STM32_PREDIV1 | STM32_PREDIV1SRC; - - /* PLL2 setup, if activated.*/ -#if STM32_ACTIVATE_PLL2 - RCC->CR |= RCC_CR_PLL2ON; - while (!(RCC->CR & RCC_CR_PLL2RDY)) - ; /* Waits until PLL2 is stable. */ -#endif - - /* PLL3 setup, if activated.*/ -#if STM32_ACTIVATE_PLL3 - RCC->CR |= RCC_CR_PLL3ON; - while (!(RCC->CR & RCC_CR_PLL3RDY)) - ; /* Waits until PLL3 is stable. */ -#endif - - /* PLL1 setup, if activated.*/ -#if STM32_ACTIVATE_PLL1 - RCC->CFGR |= STM32_PLLMUL | STM32_PLLSRC; - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL1 is stable. */ -#endif - - /* Clock settings.*/ -#if STM32_HAS_OTG1 - RCC->CFGR = STM32_MCOSEL | STM32_OTGFSPRE | STM32_PLLMUL | STM32_PLLSRC | - STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; -#else - RCC->CFGR = STM32_MCO | STM32_PLLMUL | STM32_PLLSRC | - STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; /* Flash wait states depending on clock. */ - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif - -#if !STM32_HSI_ENABLED - RCC->CR &= ~RCC_CR_HSION; -#endif -#endif /* !STM32_NO_INIT */ -} -#else -void stm32_clock_init(void) {} -#endif - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/hal_lld.c + * @brief STM32F1xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f10x.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + +#if HAL_USE_RTC + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif /* STM32_LSE_ENABLED */ + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* Prescaler value loaded in registers.*/ + rtc_lld_set_prescaler(); + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +#endif /* HAL_USE_RTC */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) +#if defined(STM32_DMA2_CH45_HANDLER) || defined(__DOXYGEN__) +/** + * @brief DMA2 streams 4 and 5 shared ISR. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_DMA2_CH45_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 4 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM4); + + /* Check on channel 5 of DMA2.*/ + dmaServeInterrupt(STM32_DMA2_STREAM5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* defined(STM32_DMA2_CH45_HANDLER) */ +#endif /* defined(STM32_DMA_REQUIRED) */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals.*/ + rccResetAPB1(0xFFFFFFFF); + rccResetAPB2(0xFFFFFFFF); + + /* PWR and BD clocks enabled.*/ + rccEnablePWRInterface(true); + rccEnableBKPInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +#if defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) || \ + defined(STM32F10X_MD) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(__DOXYGEN__) +/* + * Clocks initialization for all sub-families except CL. + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Waits until HSI is selected. */ + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Clock settings.*/ +#if STM32_HAS_USB + RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE | + STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE; +#else + RCC->CFGR = STM32_MCOSEL | STM32_PLLMUL | STM32_PLLXTPRE | + STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE; +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + /* Switches clock source.*/ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; /* Waits selection complete. */ +#endif + +#if !STM32_HSI_ENABLED + RCC->CR &= ~RCC_CR_HSION; +#endif +#endif /* !STM32_NO_INIT */ +} + +#elif defined(STM32F10X_CL) +/* + * Clocks initialization for the CL sub-family. + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. Clearing the register has to be postponed after HSI is the + new source.*/ + RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers finally cleared to reset values.*/ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + + /* Settings of various dividers and multipliers in CFGR2.*/ + RCC->CFGR2 = STM32_PLL3MUL | STM32_PLL2MUL | STM32_PREDIV2 | + STM32_PREDIV1 | STM32_PREDIV1SRC; + + /* PLL2 setup, if activated.*/ +#if STM32_ACTIVATE_PLL2 + RCC->CR |= RCC_CR_PLL2ON; + while (!(RCC->CR & RCC_CR_PLL2RDY)) + ; /* Waits until PLL2 is stable. */ +#endif + + /* PLL3 setup, if activated.*/ +#if STM32_ACTIVATE_PLL3 + RCC->CR |= RCC_CR_PLL3ON; + while (!(RCC->CR & RCC_CR_PLL3RDY)) + ; /* Waits until PLL3 is stable. */ +#endif + + /* PLL1 setup, if activated.*/ +#if STM32_ACTIVATE_PLL1 + RCC->CFGR |= STM32_PLLMUL | STM32_PLLSRC; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL1 is stable. */ +#endif + + /* Clock settings.*/ +#if STM32_HAS_OTG1 + RCC->CFGR = STM32_MCOSEL | STM32_OTGFSPRE | STM32_PLLMUL | STM32_PLLSRC | + STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; +#else + RCC->CFGR = STM32_MCO | STM32_PLLMUL | STM32_PLLSRC | + STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; /* Flash wait states depending on clock. */ + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif + +#if !STM32_HSI_ENABLED + RCC->CR &= ~RCC_CR_HSION; +#endif +#endif /* !STM32_NO_INIT */ +} +#else +void stm32_clock_init(void) {} +#endif + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_lld.h b/os/hal/ports/STM32/STM32F1xx/hal_lld.h index 908276dc65..0666df4b66 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32F1xx/hal_lld.h @@ -1,245 +1,245 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/hal_lld.h - * @brief STM32F1xx HAL subsystem low level driver header. - * @pre This module requires the following macros to be defined in the - * @p board.h file: - * - STM32_LSECLK. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32F100xB for Value Line Medium Density devices. - * - STM32F100xE for Value Line High Density devices. - * - STM32F101x6, STM32F102x6, STM32F103x6 for Performance - * Low Density devices. - * - STM32F101xB, STM32F102xB, STM32F103xB for Performance - * Medium Density devices. - * - STM32F101xE, STM32F103xE for Performance High Density devices. - * - STM32F101xG, STM32F103xG for Performance eXtra Density devices. - * - STM32F105xC, STM32F107xC for Connectivity Line devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F1xx" - -#elif defined(STM32F10X_MD_VL) -#define PLATFORM_NAME "STM32F100 Value Line Medium Density" - -#elif defined(STM32F10X_HD_VL) -#define PLATFORM_NAME "STM32F100 Value Line High Density" - -#elif defined(STM32F10X_LD) -#define PLATFORM_NAME "STM32F10x Performance Line Low Density" - -#elif defined(STM32F10X_MD) -#define PLATFORM_NAME "STM32F10x Performance Line Medium Density" - -#elif defined(STM32F10X_HD) -#define PLATFORM_NAME "STM32F10x Performance Line High Density" - -#elif defined(STM32F10X_XL) -#define PLATFORM_NAME "STM32F10x Performance Line eXtra Density" - -#elif defined(STM32F10X_CL) -#define PLATFORM_NAME "STM32F10x Connectivity Line" - -#else -#error "unsupported or unrecognized STM32F1xx member" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32F1XX) || defined(__DOXYGEN__) -#define STM32F1XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 8000000 /**< High speed internal clock. */ -#define STM32_LSICLK 40000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @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 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if defined(STM32F10X_MD_VL) || defined(STM32F10X_HD_VL) || \ - defined(__DOXYGEN__) -#include "hal_lld_f100.h" - -#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ - defined(__DOXYGEN__) -#include "hal_lld_f103.h" - -#elif defined(STM32F10X_CL) || defined(__DOXYGEN__) -#include "hal_lld_f105_f107.h" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/hal_lld.h + * @brief STM32F1xx HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - STM32_LSECLK. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32F100xB for Value Line Medium Density devices. + * - STM32F100xE for Value Line High Density devices. + * - STM32F101x6, STM32F102x6, STM32F103x6 for Performance + * Low Density devices. + * - STM32F101xB, STM32F102xB, STM32F103xB for Performance + * Medium Density devices. + * - STM32F101xE, STM32F103xE for Performance High Density devices. + * - STM32F101xG, STM32F103xG for Performance eXtra Density devices. + * - STM32F105xC, STM32F107xC for Connectivity Line devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F1xx" + +#elif defined(STM32F10X_MD_VL) +#define PLATFORM_NAME "STM32F100 Value Line Medium Density" + +#elif defined(STM32F10X_HD_VL) +#define PLATFORM_NAME "STM32F100 Value Line High Density" + +#elif defined(STM32F10X_LD) +#define PLATFORM_NAME "STM32F10x Performance Line Low Density" + +#elif defined(STM32F10X_MD) +#define PLATFORM_NAME "STM32F10x Performance Line Medium Density" + +#elif defined(STM32F10X_HD) +#define PLATFORM_NAME "STM32F10x Performance Line High Density" + +#elif defined(STM32F10X_XL) +#define PLATFORM_NAME "STM32F10x Performance Line eXtra Density" + +#elif defined(STM32F10X_CL) +#define PLATFORM_NAME "STM32F10x Connectivity Line" + +#else +#error "unsupported or unrecognized STM32F1xx member" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32F1XX) || defined(__DOXYGEN__) +#define STM32F1XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 8000000 /**< High speed internal clock. */ +#define STM32_LSICLK 40000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @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 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if defined(STM32F10X_MD_VL) || defined(STM32F10X_HD_VL) || \ + defined(__DOXYGEN__) +#include "hal_lld_f100.h" + +#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ + defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(__DOXYGEN__) +#include "hal_lld_f103.h" + +#elif defined(STM32F10X_CL) || defined(__DOXYGEN__) +#include "hal_lld_f105_f107.h" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_lld_f100.h b/os/hal/ports/STM32/STM32F1xx/hal_lld_f100.h index 65d8571278..46c1d2cedf 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_lld_f100.h +++ b/os/hal/ports/STM32/STM32F1xx/hal_lld_f100.h @@ -1,575 +1,583 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @defgroup STM32F100_HAL STM32F100 HAL Support - * @details HAL support for STM32 Value Line LD, MD and HD sub-families. - * - * @ingroup HAL - */ - -/** - * @file STM32F1xx/hal_lld_f100.h - * @brief STM32F100 Value Line HAL subsystem low level driver header. - * - * @addtogroup STM32F100_HAL - * @{ - */ - -#ifndef _HAL_LLD_F100_H_ -#define _HAL_LLD_F100_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 24000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 24000000 - -/** - * @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 24000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 24000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 24000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 24000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 12000000 -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_ADCPRE_DIV2 (0 << 14) /**< PPRE2 divided by 2. */ -#define STM32_ADCPRE_DIV4 (1 << 14) /**< PPRE2 divided by 4. */ -#define STM32_ADCPRE_DIV6 (2 << 14) /**< PPRE2 divided by 6. */ -#define STM32_ADCPRE_DIV8 (3 << 14) /**< PPRE2 divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ - -#define STM32_PLLXTPRE_DIV1 (0 << 17) /**< HSE divided by 1. */ -#define STM32_PLLXTPRE_DIV2 (1 << 17) /**< HSE divided by 2. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 128 used as - RTC clock. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @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 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLXTPRE) || defined(__DOXYGEN__) -#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 24MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 3 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 24MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief ADC prescaler value. - */ -#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADCPRE STM32_ADCPRE_DIV2 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F100_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F100_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSELSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE prescaler setting check.*/ -#if (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV1) && \ - (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV2) -#error "invalid STM32_PLLXTPRE value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#if STM32_PLLXTPRE == STM32_PLLXTPRE_DIV1 -#define STM32_PLLCLKIN (STM32_HSECLK / 1) -#else -#define STM32_PLLCLKIN (STM32_HSECLK / 2) -#endif -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL 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 - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 128) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC 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) -#else -#error "invalid STM32_ADCPRE value specified" -#endif - -/* ADC frequency check.*/ -#if STM32_ADCCLK > STM32_ADCCLK_MAX -#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/** - * @brief Timers 2, 3, 4, 5, 6, 7, 12, 13, 14 clock. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 1, 8, 9, 10, 11 clock. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#elif STM32_HCLK <= 48000000 -#define STM32_FLASHBITS 0x00000011 -#else -#define STM32_FLASHBITS 0x00000012 -#endif - -#endif /* _HAL_LLD_F100_H_ */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @defgroup STM32F100_HAL STM32F100 HAL Support + * @details HAL support for STM32 Value Line LD, MD and HD sub-families. + * + * @ingroup HAL + */ + +/** + * @file STM32F1xx/hal_lld_f100.h + * @brief STM32F100 Value Line HAL subsystem low level driver header. + * + * @addtogroup STM32F100_HAL + * @{ + */ + +#ifndef _HAL_LLD_F100_H_ +#define _HAL_LLD_F100_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 24000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 24000000 + +/** + * @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 24000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 24000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 24000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 24000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 12000000 +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_ADCPRE_DIV2 (0 << 14) /**< PPRE2 divided by 2. */ +#define STM32_ADCPRE_DIV4 (1 << 14) /**< PPRE2 divided by 4. */ +#define STM32_ADCPRE_DIV6 (2 << 14) /**< PPRE2 divided by 6. */ +#define STM32_ADCPRE_DIV8 (3 << 14) /**< PPRE2 divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ + +#define STM32_PLLXTPRE_DIV1 (0 << 17) /**< HSE divided by 1. */ +#define STM32_PLLXTPRE_DIV2 (1 << 17) /**< HSE divided by 2. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 128 used as + RTC clock. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @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 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLXTPRE) || defined(__DOXYGEN__) +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 24MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 3 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 24MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief ADC prescaler value. + */ +#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADCPRE STM32_ADCPRE_DIV2 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F100_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F100_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSELSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE prescaler setting check.*/ +#if (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV1) && \ + (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV2) +#error "invalid STM32_PLLXTPRE value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#if STM32_PLLXTPRE == STM32_PLLXTPRE_DIV1 +#define STM32_PLLCLKIN (STM32_HSECLK / 1) +#else +#define STM32_PLLCLKIN (STM32_HSECLK / 2) +#endif +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL 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 + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 128) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC 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) +#else +#error "invalid STM32_ADCPRE value specified" +#endif + +/* ADC frequency check.*/ +#if STM32_ADCCLK > STM32_ADCCLK_MAX +#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/** + * @brief Timers 2, 3, 4, 5, 6, 7, 12, 13, 14 clock. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 1, 8, 9, 10, 11 clock. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#elif STM32_HCLK <= 48000000 +#define STM32_FLASHBITS 0x00000011 +#else +#define STM32_FLASHBITS 0x00000012 +#endif + +#endif /* _HAL_LLD_F100_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_lld_f103.h b/os/hal/ports/STM32/STM32F1xx/hal_lld_f103.h index 64c27deaa4..cb1bdb8748 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_lld_f103.h +++ b/os/hal/ports/STM32/STM32F1xx/hal_lld_f103.h @@ -1,604 +1,612 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @defgroup STM32F103_HAL STM32F103 HAL Support - * @details HAL support for STM32 Performance Line LD, MD and HD sub-families. - * - * @ingroup HAL - */ - -/** - * @file STM32F1xx/hal_lld_f103.h - * @brief STM32F103 Performance Line HAL subsystem low level driver header. - * - * @addtogroup STM32F103_HAL - * @{ - */ - -#ifndef _HAL_LLD_F103_H_ -#define _HAL_LLD_F103_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 72000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 25000000 - -/** - * @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 25000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 72000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 36000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 72000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 14000000 -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_ADCPRE_DIV2 (0 << 14) /**< PPRE2 divided by 2. */ -#define STM32_ADCPRE_DIV4 (1 << 14) /**< PPRE2 divided by 4. */ -#define STM32_ADCPRE_DIV6 (2 << 14) /**< PPRE2 divided by 6. */ -#define STM32_ADCPRE_DIV8 (3 << 14) /**< PPRE2 divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ - -#define STM32_PLLXTPRE_DIV1 (0 << 17) /**< HSE divided by 1. */ -#define STM32_PLLXTPRE_DIV2 (1 << 17) /**< HSE divided by 2. */ - -#define STM32_USBPRE_DIV1P5 (0 << 22) /**< PLLOUT divided by 1.5. */ -#define STM32_USBPRE_DIV1 (1 << 22) /**< PLLOUT divided by 1. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 128 used as - RTC clock. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @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 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLXTPRE) || defined(__DOXYGEN__) -#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 9 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief ADC prescaler value. - */ -#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#endif - -/** - * @brief USB clock setting. - */ -#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) -#define STM32_USB_CLOCK_REQUIRED TRUE -#endif - -/** - * @brief USB prescaler initialization. - */ -#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) -#define STM32_USBPRE STM32_USBPRE_DIV1P5 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F103_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F103_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if STM32_USB_CLOCK_REQUIRED || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE prescaler setting check.*/ -#if (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV1) && \ - (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV2) -#error "invalid STM32_PLLXTPRE value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#if STM32_PLLXTPRE == STM32_PLLXTPRE_DIV1 -#define STM32_PLLCLKIN (STM32_HSECLK / 1) -#else -#define STM32_PLLCLKIN (STM32_HSECLK / 2) -#endif -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL 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 - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 128) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC 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) -#else -#error "invalid STM32_ADCPRE value specified" -#endif - -/* ADC frequency check.*/ -#if STM32_ADCCLK > STM32_ADCCLK_MAX -#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/** - * @brief USB frequency. - */ -#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) -#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) -#elif (STM32_USBPRE == STM32_USBPRE_DIV1) -#define STM32_USBCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_USBPRE value specified" -#endif - -/** - * @brief Timers 2, 3, 4, 5, 6, 7, 12, 13, 14 clock. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 1, 8, 9, 10, 11 clock. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#elif STM32_HCLK <= 48000000 -#define STM32_FLASHBITS 0x00000011 -#else -#define STM32_FLASHBITS 0x00000012 -#endif - -#endif /* _HAL_LLD_F103_H_ */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @defgroup STM32F103_HAL STM32F103 HAL Support + * @details HAL support for STM32 Performance Line LD, MD and HD sub-families. + * + * @ingroup HAL + */ + +/** + * @file STM32F1xx/hal_lld_f103.h + * @brief STM32F103 Performance Line HAL subsystem low level driver header. + * + * @addtogroup STM32F103_HAL + * @{ + */ + +#ifndef _HAL_LLD_F103_H_ +#define _HAL_LLD_F103_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 72000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 25000000 + +/** + * @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 25000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 72000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 36000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 72000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 14000000 +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_ADCPRE_DIV2 (0 << 14) /**< PPRE2 divided by 2. */ +#define STM32_ADCPRE_DIV4 (1 << 14) /**< PPRE2 divided by 4. */ +#define STM32_ADCPRE_DIV6 (2 << 14) /**< PPRE2 divided by 6. */ +#define STM32_ADCPRE_DIV8 (3 << 14) /**< PPRE2 divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ + +#define STM32_PLLXTPRE_DIV1 (0 << 17) /**< HSE divided by 1. */ +#define STM32_PLLXTPRE_DIV2 (1 << 17) /**< HSE divided by 2. */ + +#define STM32_USBPRE_DIV1P5 (0 << 22) /**< PLLOUT divided by 1.5. */ +#define STM32_USBPRE_DIV1 (1 << 22) /**< PLLOUT divided by 1. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 128 used as + RTC clock. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @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 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLXTPRE) || defined(__DOXYGEN__) +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 9 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief ADC prescaler value. + */ +#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#endif + +/** + * @brief USB clock setting. + */ +#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) +#define STM32_USB_CLOCK_REQUIRED TRUE +#endif + +/** + * @brief USB prescaler initialization. + */ +#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) +#define STM32_USBPRE STM32_USBPRE_DIV1P5 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F103_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F103_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if STM32_USB_CLOCK_REQUIRED || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE prescaler setting check.*/ +#if (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV1) && \ + (STM32_PLLXTPRE != STM32_PLLXTPRE_DIV2) +#error "invalid STM32_PLLXTPRE value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#if STM32_PLLXTPRE == STM32_PLLXTPRE_DIV1 +#define STM32_PLLCLKIN (STM32_HSECLK / 1) +#else +#define STM32_PLLCLKIN (STM32_HSECLK / 2) +#endif +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL 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 + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 128) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC 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) +#else +#error "invalid STM32_ADCPRE value specified" +#endif + +/* ADC frequency check.*/ +#if STM32_ADCCLK > STM32_ADCCLK_MAX +#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/** + * @brief USB frequency. + */ +#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) +#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) +#elif (STM32_USBPRE == STM32_USBPRE_DIV1) +#define STM32_USBCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_USBPRE value specified" +#endif + +/** + * @brief Timers 2, 3, 4, 5, 6, 7, 12, 13, 14 clock. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 1, 8, 9, 10, 11 clock. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#elif STM32_HCLK <= 48000000 +#define STM32_FLASHBITS 0x00000011 +#else +#define STM32_FLASHBITS 0x00000012 +#endif + +#endif /* _HAL_LLD_F103_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/hal_lld_f105_f107.h b/os/hal/ports/STM32/STM32F1xx/hal_lld_f105_f107.h index efbe94deb6..e429dff5f7 100644 --- a/os/hal/ports/STM32/STM32F1xx/hal_lld_f105_f107.h +++ b/os/hal/ports/STM32/STM32F1xx/hal_lld_f105_f107.h @@ -1,814 +1,822 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @defgroup STM32F10X_CL_HAL STM32F105/F107 HAL Support - * @details HAL support for STM32 Connectivity Line sub-family. - * - * @ingroup HAL - */ - -/** - * @file STM32F1xx/hal_lld_f105_f107.h - * @brief STM32F10x Connectivity Line HAL subsystem low level driver header. - * - * @addtogroup STM32F10X_CL_HAL - * @{ - */ - -#ifndef _HAL_LLD_F105_F107_H_ -#define _HAL_LLD_F105_F107_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 72000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 50000000 - -/** - * @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_PLL1IN_MAX 12000000 - -/** - * @brief Minimum PLL1 input clock frequency. - */ -#define STM32_PLL1IN_MIN 3000000 - -/** - * @brief Maximum PLL1 input clock frequency. - */ -#define STM32_PLL23IN_MAX 5000000 - -/** - * @brief Minimum PLL2 and PLL3 input clock frequency. - */ -#define STM32_PLL23IN_MIN 3000000 - -/** - * @brief Maximum PLL1 VCO clock frequency. - */ -#define STM32_PLL1VCO_MAX 144000000 - -/** - * @brief Minimum PLL1 VCO clock frequency. - */ -#define STM32_PLL1VCO_MIN 36000000 - -/** - * @brief Maximum PLL2 and PLL3 VCO clock frequency. - */ -#define STM32_PLL23VCO_MAX 148000000 - -/** - * @brief Minimum PLL2 and PLL3 VCO clock frequency. - */ -#define STM32_PLL23VCO_MIN 80000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 36000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 72000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 14000000 - -/** - * @brief Maximum SPI/I2S clock frequency. - */ -#define STM32_SPII2S_MAX 18000000 -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_ADCPRE_DIV2 (0 << 14) /**< PPRE2 divided by 2. */ -#define STM32_ADCPRE_DIV4 (1 << 14) /**< PPRE2 divided by 4. */ -#define STM32_ADCPRE_DIV6 (2 << 14) /**< PPRE2 divided by 6. */ -#define STM32_ADCPRE_DIV8 (3 << 14) /**< PPRE2 divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_PREDIV1 (1 << 16) /**< PLL clock source is - PREDIV1. */ - -#define STM32_OTGFSPRE_DIV2 (1 << 22) /**< HCLK*2 divided by 2. */ -#define STM32_OTGFSPRE_DIV3 (0 << 22) /**< HCLK*2 divided by 3. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -#define STM32_MCOSEL_PLL2 (8 << 24) /**< PLL2 clock on MCO pin. */ -#define STM32_MCOSEL_PLL3DIV2 (9 << 24) /**< PLL3/2 clock on MCO pin. */ -#define STM32_MCOSEL_XT1 (10 << 24) /**< XT1 clock on MCO pin. */ -#define STM32_MCOSEL_PLL3 (11 << 24) /**< PLL3 clock on MCO pin. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 128 used as - RTC clock. */ -/** @} */ - -/** - * @name RCC_CFGR2 register bits definitions - * @{ - */ -#define STM32_PREDIV1SRC_HSE (0 << 16) /**< PREDIV1 source is HSE. */ -#define STM32_PREDIV1SRC_PLL2 (1 << 16) /**< PREDIV1 source is PLL2. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Main clock source selection. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_PREDIV1 -#endif - -/** - * @brief PREDIV1 clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_PREDIV1SRC) || defined(__DOXYGEN__) -#define STM32_PREDIV1SRC STM32_PREDIV1SRC_HSE -#endif - -/** - * @brief PREDIV1 division factor. - * @note The allowed range is 1...16. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_PREDIV1_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV1_VALUE 5 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 4...9. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 9 -#endif - -/** - * @brief PREDIV2 division factor. - * @note The allowed range is 1...16. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_PREDIV2_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV2_VALUE 5 -#endif - -/** - * @brief PLL2 multiplier value. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_PLL2MUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2MUL_VALUE 8 -#endif - -/** - * @brief PLL3 multiplier value. - * @note The default value is calculated for a 50MHz clock from - * a 25MHz crystal. - */ -#if !defined(STM32_PLL3MUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3MUL_VALUE 10 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 72MHz system clock from - * a 25MHz crystal using both PLL and PLL2. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief ADC prescaler value. - */ -#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#endif - -/** - * @brief USB clock setting. - */ -#if !defined(STM32_OTG_CLOCK_REQUIRED) || defined(__DOXYGEN__) -#define STM32_OTG_CLOCK_REQUIRED TRUE -#endif - -/** - * @brief OTG prescaler initialization. - */ -#if !defined(STM32_OTGFSPRE) || defined(__DOXYGEN__) -#define STM32_OTGFSPRE STM32_OTGFSPRE_DIV3 -#endif - -/** - * @brief Dedicated I2S clock setting. - */ -#if !defined(STM32_I2S_CLOCK_REQUIRED) || defined(__DOXYGEN__) -#define STM32_I2S_CLOCK_REQUIRED FALSE -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_HSEDIV -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F107_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F107_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_PREDIV1) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - (((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL2) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL3) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL3DIV2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ - (STM32_MCOSEL == STM32_MCOSEL_XT1) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL1 activation conditions.*/ -#if STM32_OTG_CLOCK_REQUIRED || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - defined(__DOXYGEN__) -/** - * @brief PLL1 activation flag. - */ -#define STM32_ACTIVATE_PLL1 TRUE -#else -#define STM32_ACTIVATE_PLL1 FALSE -#endif - -/* PLL2 activation conditions.*/ -#if ((STM32_PREDIV1SRC == STM32_PREDIV1SRC_PLL2) && STM32_ACTIVATE_PLL1) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL2) || defined(__DOXYGEN__) -/** - * @brief PLL2 activation flag. - */ -#define STM32_ACTIVATE_PLL2 TRUE -#else -#define STM32_ACTIVATE_PLL2 FALSE -#endif - -/* PLL3 activation conditions.*/ -#if STM32_I2S_CLOCK_REQUIRED || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL3DIV2) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL3) || \ - defined(__DOXYGEN__) -/** - * @brief PLL3 activation flag. - */ -#define STM32_ACTIVATE_PLL3 TRUE -#else -#define STM32_ACTIVATE_PLL3 FALSE -#endif - -/** - * @brief PREDIV1 field. - */ -#if (STM32_PREDIV1_VALUE >= 1) && (STM32_PREDIV1_VALUE <= 16) || \ - defined(__DOXYGEN__) -#define STM32_PREDIV1 ((STM32_PREDIV1_VALUE - 1) << 0) -#else -#error "invalid STM32_PREDIV1_VALUE value specified" -#endif - -/** - * @brief PREDIV2 field. - */ -#if (STM32_PREDIV2_VALUE >= 1) && (STM32_PREDIV2_VALUE <= 16) || \ - defined(__DOXYGEN__) -#define STM32_PREDIV2 ((STM32_PREDIV2_VALUE - 1) << 4) -#else -#error "invalid STM32_PREDIV2_VALUE value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 4) && (STM32_PLLMUL_VALUE <= 9)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL2MUL field. - */ -#if ((STM32_PLL2MUL_VALUE >= 8) && (STM32_PLL2MUL_VALUE <= 14)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2MUL ((STM32_PLL2MUL_VALUE - 2) << 8) -#elif (STM32_PLL2MUL_VALUE == 16) -#define STM32_PLL2MUL (14 << 8) -#elif (STM32_PLL2MUL_VALUE == 20) -#define STM32_PLL2MUL (15 << 8) -#else -#error "invalid STM32_PLL2MUL_VALUE value specified" -#endif - -/** - * @brief PLL3MUL field. - */ -#if ((STM32_PLL3MUL_VALUE >= 8) && (STM32_PLL3MUL_VALUE <= 14)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3MUL ((STM32_PLL3MUL_VALUE - 2) << 12) -#elif (STM32_PLL3MUL_VALUE == 16) -#define STM32_PLL3MUL (14 << 12) -#elif (STM32_PLL3MUL_VALUE == 20) -#define STM32_PLL3MUL (15 << 12) -#else -#error "invalid STM32_PLL3MUL_VALUE value specified" -#endif - -/** - * @brief PLL2 input frequency. - */ -#define STM32_PLL2CLKIN (STM32_HSECLK / STM32_PREDIV2_VALUE) - -/* PLL2 input frequency range check.*/ -#if (STM32_PLL2CLKIN < STM32_PLL23IN_MIN) || \ - (STM32_PLL2CLKIN > STM32_PLL23IN_MAX) -#error "STM32_PLL2CLKIN outside acceptable range (STM32_PLL23IN_MIN...STM32_PLL23IN_MAX)" -#endif - -/** - * @brief PLL2 output clock frequency. - */ -#define STM32_PLL2CLKOUT (STM32_PLL2CLKIN * STM32_PLL2MUL_VALUE) - -/** - * @brief PLL2 VCO clock frequency. - */ -#define STM32_PLL2VCO (STM32_PLL2CLKOUT * 2) - -/* PLL2 output frequency range check.*/ -#if (STM32_PLL2VCO < STM32_PLL23VCO_MIN) || \ - (STM32_PLL2VCO > STM32_PLL23VCO_MAX) -#error "STM32_PLL2VCO outside acceptable range (STM32_PLL23VCO_MIN...STM32_PLL23VCO_MAX)" -#endif - -/** - * @brief PLL3 input frequency. - */ -#define STM32_PLL3CLKIN (STM32_HSECLK / STM32_PREDIV2_VALUE) - -/* PLL3 input frequency range check.*/ -#if (STM32_PLL3CLKIN < STM32_PLL23IN_MIN) || \ - (STM32_PLL3CLKIN > STM32_PLL23IN_MAX) -#error "STM32_PLL3CLKIN outside acceptable range (STM32_PLL23IN_MIN...STM32_PLL23IN_MAX)" -#endif - -/** - * @brief PLL3 output clock frequency. - */ -#define STM32_PLL3CLKOUT (STM32_PLL3CLKIN * STM32_PLL3MUL_VALUE) - -/** - * @brief PLL3 VCO clock frequency. - */ -#define STM32_PLL3VCO (STM32_PLL3CLKOUT * 2) - -/* PLL3 output frequency range check.*/ -#if (STM32_PLL3VCO < STM32_PLL23VCO_MIN) || \ - (STM32_PLL3VCO > STM32_PLL23VCO_MAX) -#error "STM32_PLL3CLKOUT outside acceptable range (STM32_PLL23VCO_MIN...STM32_PLL23VCO_MAX)" -#endif - -/** - * @brief PREDIV1 input frequency. - */ -#if (STM32_PREDIV1SRC == STM32_PREDIV1SRC_HSE) || defined(__DOXYGEN__) -#define STM32_PREDIV1CLK STM32_HSECLK -#elif STM32_PREDIV1SRC == STM32_PREDIV1SRC_PLL2 -#define STM32_PREDIV1CLK STM32_PLL2CLKOUT -#else -#error "invalid STM32_PREDIV1SRC value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_PREDIV1) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_PREDIV1CLK / STM32_PREDIV1_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL input frequency range check.*/ -#if (STM32_PLLCLKIN < STM32_PLL1IN_MIN) || (STM32_PLLCLKIN > STM32_PLL1IN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLL1IN_MIN...STM32_PLL1IN_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/** - * @brief PLL VCO clock frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKOUT * 2) - -/* PLL output frequency range check.*/ -#if (STM32_PLLVCO < STM32_PLL1VCO_MIN) || (STM32_PLLVCO > STM32_PLL1VCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLL1VCO_MIN...STM32_PLL1VCO_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 128) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC 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) -#else -#error "invalid STM32_ADCPRE value specified" -#endif - -/* ADC frequency check.*/ -#if STM32_ADCCLK > STM32_ADCCLK_MAX -#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#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" -#endif - -/** - * @brief Timers 2, 3, 4, 5, 6, 7 clock. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 1, 8 clock. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#elif STM32_HCLK <= 48000000 -#define STM32_FLASHBITS 0x00000011 -#else -#define STM32_FLASHBITS 0x00000012 -#endif - -#endif /* _HAL_LLD_F105_F107_H_ */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @defgroup STM32F10X_CL_HAL STM32F105/F107 HAL Support + * @details HAL support for STM32 Connectivity Line sub-family. + * + * @ingroup HAL + */ + +/** + * @file STM32F1xx/hal_lld_f105_f107.h + * @brief STM32F10x Connectivity Line HAL subsystem low level driver header. + * + * @addtogroup STM32F10X_CL_HAL + * @{ + */ + +#ifndef _HAL_LLD_F105_F107_H_ +#define _HAL_LLD_F105_F107_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 72000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 50000000 + +/** + * @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_PLL1IN_MAX 12000000 + +/** + * @brief Minimum PLL1 input clock frequency. + */ +#define STM32_PLL1IN_MIN 3000000 + +/** + * @brief Maximum PLL1 input clock frequency. + */ +#define STM32_PLL23IN_MAX 5000000 + +/** + * @brief Minimum PLL2 and PLL3 input clock frequency. + */ +#define STM32_PLL23IN_MIN 3000000 + +/** + * @brief Maximum PLL1 VCO clock frequency. + */ +#define STM32_PLL1VCO_MAX 144000000 + +/** + * @brief Minimum PLL1 VCO clock frequency. + */ +#define STM32_PLL1VCO_MIN 36000000 + +/** + * @brief Maximum PLL2 and PLL3 VCO clock frequency. + */ +#define STM32_PLL23VCO_MAX 148000000 + +/** + * @brief Minimum PLL2 and PLL3 VCO clock frequency. + */ +#define STM32_PLL23VCO_MIN 80000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 36000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 72000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 14000000 + +/** + * @brief Maximum SPI/I2S clock frequency. + */ +#define STM32_SPII2S_MAX 18000000 +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_ADCPRE_DIV2 (0 << 14) /**< PPRE2 divided by 2. */ +#define STM32_ADCPRE_DIV4 (1 << 14) /**< PPRE2 divided by 4. */ +#define STM32_ADCPRE_DIV6 (2 << 14) /**< PPRE2 divided by 6. */ +#define STM32_ADCPRE_DIV8 (3 << 14) /**< PPRE2 divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_PREDIV1 (1 << 16) /**< PLL clock source is + PREDIV1. */ + +#define STM32_OTGFSPRE_DIV2 (1 << 22) /**< HCLK*2 divided by 2. */ +#define STM32_OTGFSPRE_DIV3 (0 << 22) /**< HCLK*2 divided by 3. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +#define STM32_MCOSEL_PLL2 (8 << 24) /**< PLL2 clock on MCO pin. */ +#define STM32_MCOSEL_PLL3DIV2 (9 << 24) /**< PLL3/2 clock on MCO pin. */ +#define STM32_MCOSEL_XT1 (10 << 24) /**< XT1 clock on MCO pin. */ +#define STM32_MCOSEL_PLL3 (11 << 24) /**< PLL3 clock on MCO pin. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 128 used as + RTC clock. */ +/** @} */ + +/** + * @name RCC_CFGR2 register bits definitions + * @{ + */ +#define STM32_PREDIV1SRC_HSE (0 << 16) /**< PREDIV1 source is HSE. */ +#define STM32_PREDIV1SRC_PLL2 (1 << 16) /**< PREDIV1 source is PLL2. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Main clock source selection. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_PREDIV1 +#endif + +/** + * @brief PREDIV1 clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_PREDIV1SRC) || defined(__DOXYGEN__) +#define STM32_PREDIV1SRC STM32_PREDIV1SRC_HSE +#endif + +/** + * @brief PREDIV1 division factor. + * @note The allowed range is 1...16. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_PREDIV1_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV1_VALUE 5 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 4...9. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 9 +#endif + +/** + * @brief PREDIV2 division factor. + * @note The allowed range is 1...16. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_PREDIV2_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV2_VALUE 5 +#endif + +/** + * @brief PLL2 multiplier value. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_PLL2MUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2MUL_VALUE 8 +#endif + +/** + * @brief PLL3 multiplier value. + * @note The default value is calculated for a 50MHz clock from + * a 25MHz crystal. + */ +#if !defined(STM32_PLL3MUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3MUL_VALUE 10 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 72MHz system clock from + * a 25MHz crystal using both PLL and PLL2. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief ADC prescaler value. + */ +#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#endif + +/** + * @brief USB clock setting. + */ +#if !defined(STM32_OTG_CLOCK_REQUIRED) || defined(__DOXYGEN__) +#define STM32_OTG_CLOCK_REQUIRED TRUE +#endif + +/** + * @brief OTG prescaler initialization. + */ +#if !defined(STM32_OTGFSPRE) || defined(__DOXYGEN__) +#define STM32_OTGFSPRE STM32_OTGFSPRE_DIV3 +#endif + +/** + * @brief Dedicated I2S clock setting. + */ +#if !defined(STM32_I2S_CLOCK_REQUIRED) || defined(__DOXYGEN__) +#define STM32_I2S_CLOCK_REQUIRED FALSE +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_HSEDIV +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F107_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F107_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_PREDIV1) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + (((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL2) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL3) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL3DIV2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ + (STM32_MCOSEL == STM32_MCOSEL_XT1) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL1 activation conditions.*/ +#if STM32_OTG_CLOCK_REQUIRED || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + defined(__DOXYGEN__) +/** + * @brief PLL1 activation flag. + */ +#define STM32_ACTIVATE_PLL1 TRUE +#else +#define STM32_ACTIVATE_PLL1 FALSE +#endif + +/* PLL2 activation conditions.*/ +#if ((STM32_PREDIV1SRC == STM32_PREDIV1SRC_PLL2) && STM32_ACTIVATE_PLL1) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL2) || defined(__DOXYGEN__) +/** + * @brief PLL2 activation flag. + */ +#define STM32_ACTIVATE_PLL2 TRUE +#else +#define STM32_ACTIVATE_PLL2 FALSE +#endif + +/* PLL3 activation conditions.*/ +#if STM32_I2S_CLOCK_REQUIRED || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL3DIV2) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL3) || \ + defined(__DOXYGEN__) +/** + * @brief PLL3 activation flag. + */ +#define STM32_ACTIVATE_PLL3 TRUE +#else +#define STM32_ACTIVATE_PLL3 FALSE +#endif + +/** + * @brief PREDIV1 field. + */ +#if (STM32_PREDIV1_VALUE >= 1) && (STM32_PREDIV1_VALUE <= 16) || \ + defined(__DOXYGEN__) +#define STM32_PREDIV1 ((STM32_PREDIV1_VALUE - 1) << 0) +#else +#error "invalid STM32_PREDIV1_VALUE value specified" +#endif + +/** + * @brief PREDIV2 field. + */ +#if (STM32_PREDIV2_VALUE >= 1) && (STM32_PREDIV2_VALUE <= 16) || \ + defined(__DOXYGEN__) +#define STM32_PREDIV2 ((STM32_PREDIV2_VALUE - 1) << 4) +#else +#error "invalid STM32_PREDIV2_VALUE value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 4) && (STM32_PLLMUL_VALUE <= 9)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL2MUL field. + */ +#if ((STM32_PLL2MUL_VALUE >= 8) && (STM32_PLL2MUL_VALUE <= 14)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2MUL ((STM32_PLL2MUL_VALUE - 2) << 8) +#elif (STM32_PLL2MUL_VALUE == 16) +#define STM32_PLL2MUL (14 << 8) +#elif (STM32_PLL2MUL_VALUE == 20) +#define STM32_PLL2MUL (15 << 8) +#else +#error "invalid STM32_PLL2MUL_VALUE value specified" +#endif + +/** + * @brief PLL3MUL field. + */ +#if ((STM32_PLL3MUL_VALUE >= 8) && (STM32_PLL3MUL_VALUE <= 14)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3MUL ((STM32_PLL3MUL_VALUE - 2) << 12) +#elif (STM32_PLL3MUL_VALUE == 16) +#define STM32_PLL3MUL (14 << 12) +#elif (STM32_PLL3MUL_VALUE == 20) +#define STM32_PLL3MUL (15 << 12) +#else +#error "invalid STM32_PLL3MUL_VALUE value specified" +#endif + +/** + * @brief PLL2 input frequency. + */ +#define STM32_PLL2CLKIN (STM32_HSECLK / STM32_PREDIV2_VALUE) + +/* PLL2 input frequency range check.*/ +#if (STM32_PLL2CLKIN < STM32_PLL23IN_MIN) || \ + (STM32_PLL2CLKIN > STM32_PLL23IN_MAX) +#error "STM32_PLL2CLKIN outside acceptable range (STM32_PLL23IN_MIN...STM32_PLL23IN_MAX)" +#endif + +/** + * @brief PLL2 output clock frequency. + */ +#define STM32_PLL2CLKOUT (STM32_PLL2CLKIN * STM32_PLL2MUL_VALUE) + +/** + * @brief PLL2 VCO clock frequency. + */ +#define STM32_PLL2VCO (STM32_PLL2CLKOUT * 2) + +/* PLL2 output frequency range check.*/ +#if (STM32_PLL2VCO < STM32_PLL23VCO_MIN) || \ + (STM32_PLL2VCO > STM32_PLL23VCO_MAX) +#error "STM32_PLL2VCO outside acceptable range (STM32_PLL23VCO_MIN...STM32_PLL23VCO_MAX)" +#endif + +/** + * @brief PLL3 input frequency. + */ +#define STM32_PLL3CLKIN (STM32_HSECLK / STM32_PREDIV2_VALUE) + +/* PLL3 input frequency range check.*/ +#if (STM32_PLL3CLKIN < STM32_PLL23IN_MIN) || \ + (STM32_PLL3CLKIN > STM32_PLL23IN_MAX) +#error "STM32_PLL3CLKIN outside acceptable range (STM32_PLL23IN_MIN...STM32_PLL23IN_MAX)" +#endif + +/** + * @brief PLL3 output clock frequency. + */ +#define STM32_PLL3CLKOUT (STM32_PLL3CLKIN * STM32_PLL3MUL_VALUE) + +/** + * @brief PLL3 VCO clock frequency. + */ +#define STM32_PLL3VCO (STM32_PLL3CLKOUT * 2) + +/* PLL3 output frequency range check.*/ +#if (STM32_PLL3VCO < STM32_PLL23VCO_MIN) || \ + (STM32_PLL3VCO > STM32_PLL23VCO_MAX) +#error "STM32_PLL3CLKOUT outside acceptable range (STM32_PLL23VCO_MIN...STM32_PLL23VCO_MAX)" +#endif + +/** + * @brief PREDIV1 input frequency. + */ +#if (STM32_PREDIV1SRC == STM32_PREDIV1SRC_HSE) || defined(__DOXYGEN__) +#define STM32_PREDIV1CLK STM32_HSECLK +#elif STM32_PREDIV1SRC == STM32_PREDIV1SRC_PLL2 +#define STM32_PREDIV1CLK STM32_PLL2CLKOUT +#else +#error "invalid STM32_PREDIV1SRC value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_PREDIV1) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_PREDIV1CLK / STM32_PREDIV1_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL input frequency range check.*/ +#if (STM32_PLLCLKIN < STM32_PLL1IN_MIN) || (STM32_PLLCLKIN > STM32_PLL1IN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLL1IN_MIN...STM32_PLL1IN_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/** + * @brief PLL VCO clock frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKOUT * 2) + +/* PLL output frequency range check.*/ +#if (STM32_PLLVCO < STM32_PLL1VCO_MIN) || (STM32_PLLVCO > STM32_PLL1VCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLL1VCO_MIN...STM32_PLL1VCO_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 128) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC 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) +#else +#error "invalid STM32_ADCPRE value specified" +#endif + +/* ADC frequency check.*/ +#if STM32_ADCCLK > STM32_ADCCLK_MAX +#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#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" +#endif + +/** + * @brief Timers 2, 3, 4, 5, 6, 7 clock. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 1, 8 clock. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#elif STM32_HCLK <= 48000000 +#define STM32_FLASHBITS 0x00000011 +#else +#define STM32_FLASHBITS 0x00000012 +#endif + +#endif /* _HAL_LLD_F105_F107_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/platform.mk b/os/hal/ports/STM32/STM32F1xx/platform.mk index 8ff4f53316..ddef923c70 100644 --- a/os/hal/ports/STM32/STM32F1xx/platform.mk +++ b/os/hal/ports/STM32/STM32F1xx/platform.mk @@ -1,48 +1,48 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_lld.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_lld.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_efl_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F1xx/platform_f105_f107.mk b/os/hal/ports/STM32/STM32F1xx/platform_f105_f107.mk index f44a0a3195..f4890d8999 100644 --- a/os/hal/ports/STM32/STM32F1xx/platform_f105_f107.mk +++ b/os/hal/ports/STM32/STM32F1xx/platform_f105_f107.mk @@ -1,47 +1,47 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F1xx/hal_adc_lld.c +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F1xx/stm32_isr.c b/os/hal/ports/STM32/STM32F1xx/stm32_isr.c index e0d0cfb224..1096c4643e 100644 --- a/os/hal/ports/STM32/STM32F1xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32F1xx/stm32_isr.c @@ -1,255 +1,255 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/stm32_isr.c - * @brief STM32F1xx ISR handler code. - * - * @addtogroup STM32F1xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_EXTI0_HANDLER) -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 0); - EXTI->PR = pr; - - exti_serve_irq(pr, 0); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI1_HANDLER) -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 1); - EXTI->PR = pr; - - exti_serve_irq(pr, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_HANDLER) -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 2); - EXTI->PR = pr; - - exti_serve_irq(pr, 2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI3_HANDLER) -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 3); - EXTI->PR = pr; - - exti_serve_irq(pr, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_HANDLER) -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 4); - EXTI->PR = pr; - - exti_serve_irq(pr, 4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | - (1U << 9)); - EXTI->PR = pr; - - exti_serve_irq(pr, 5); - exti_serve_irq(pr, 6); - exti_serve_irq(pr, 7); - exti_serve_irq(pr, 8); - exti_serve_irq(pr, 9); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | - (1U << 14) | (1U << 15)); - EXTI->PR = pr; - - exti_serve_irq(pr, 10); - exti_serve_irq(pr, 11); - exti_serve_irq(pr, 12); - exti_serve_irq(pr, 13); - exti_serve_irq(pr, 14); - exti_serve_irq(pr, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#endif /* HAL_USE_PAL */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - -#if HAL_USE_PAL - nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); - nvicEnableVector(EXTI2_IRQn, STM32_IRQ_EXTI2_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); -#endif -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - -#if HAL_USE_PAL - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); -#endif -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/stm32_isr.c + * @brief STM32F1xx ISR handler code. + * + * @addtogroup STM32F1xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_EXTI0_HANDLER) +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 0); + EXTI->PR = pr; + + exti_serve_irq(pr, 0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI1_HANDLER) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 1); + EXTI->PR = pr; + + exti_serve_irq(pr, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_HANDLER) +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 2); + EXTI->PR = pr; + + exti_serve_irq(pr, 2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI3_HANDLER) +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 3); + EXTI->PR = pr; + + exti_serve_irq(pr, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_HANDLER) +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 4); + EXTI->PR = pr; + + exti_serve_irq(pr, 4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | + (1U << 9)); + EXTI->PR = pr; + + exti_serve_irq(pr, 5); + exti_serve_irq(pr, 6); + exti_serve_irq(pr, 7); + exti_serve_irq(pr, 8); + exti_serve_irq(pr, 9); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | + (1U << 14) | (1U << 15)); + EXTI->PR = pr; + + exti_serve_irq(pr, 10); + exti_serve_irq(pr, 11); + exti_serve_irq(pr, 12); + exti_serve_irq(pr, 13); + exti_serve_irq(pr, 14); + exti_serve_irq(pr, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#endif /* HAL_USE_PAL */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + +#if HAL_USE_PAL + nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); + nvicEnableVector(EXTI2_IRQn, STM32_IRQ_EXTI2_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); +#endif +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +#if HAL_USE_PAL + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); +#endif +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/stm32_isr.h b/os/hal/ports/STM32/STM32F1xx/stm32_isr.h index 5b455912f8..11a9022c77 100644 --- a/os/hal/ports/STM32/STM32F1xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F1xx/stm32_isr.h @@ -1,266 +1,266 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/stm32_isr.h - * @brief STM32F3xx ISR handler header. - * - * @addtogroup STM32F1xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 -#define STM32_CAN2_TX_HANDLER Vector13C -#define STM32_CAN2_RX0_HANDLER Vector140 -#define STM32_CAN2_RX1_HANDLER Vector144 -#define STM32_CAN2_SCE_HANDLER Vector148 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 -#define STM32_CAN2_TX_NUMBER 63 -#define STM32_CAN2_RX0_NUMBER 64 -#define STM32_CAN2_RX1_NUMBER 65 -#define STM32_CAN2_SCE_NUMBER 66 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 - -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 - -/* - * OTG units. - */ -#define STM32_OTG1_HANDLER Vector14C - -#define STM32_OTG1_NUMBER 67 - -/* - * SDIO unit. - */ -#define STM32_SDIO_HANDLER Vector104 - -#define STM32_SDIO_NUMBER 49 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER VectorA4 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_CC_HANDLER VectorF8 -#define STM32_TIM9_HANDLER VectorA0 /* Note: same as STM32_TIM1_BRK */ -#define STM32_TIM10_HANDLER VectorA4 /* Note: same as STM32_TIM1_UP */ -#define STM32_TIM11_HANDLER VectorA8 /* Note: same as STM32_TIM1_TRG_COM */ -#define STM32_TIM12_HANDLER VectorEC /* Note: same as STM32_TIM8_BRK */ -#define STM32_TIM13_HANDLER VectorF0 /* Note: same as STM32_TIM8_UP */ -#define STM32_TIM14_HANDLER VectorF4 /* Note: same as STM32_TIM8_TRG_COM */ - -#define STM32_TIM1_UP_NUMBER 25 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_CC_NUMBER 46 -#define STM32_TIM9_NUMBER 24 /* Note: same as STM32_TIM1_BRK */ -#define STM32_TIM10_NUMBER 25 /* Note: same as STM32_TIM1_UP */ -#define STM32_TIM11_NUMBER 26 /* Note: same as STM32_TIM1_TRG_COM */ -#define STM32_TIM12_NUMBER 43 /* Note: same as STM32_TIM8_BRK */ -#define STM32_TIM13_NUMBER 44 /* Note: same as STM32_TIM8_UP */ -#define STM32_TIM14_NUMBER 45 /* Note: same as STM32_TIM8_TRG_COM */ - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 - -/* - * USB units. - */ -#define STM32_USB1_HP_HANDLER Vector8C -#define STM32_USB1_LP_HANDLER Vector90 - -#define STM32_USB1_HP_NUMBER 19 -#define STM32_USB1_LP_NUMBER 20 - -/* - * RTC unit - */ -#define STM32_RTC1_HANDLER Vector4C - -#define STM32_RTC1_NUMBER 3 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI0_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI1_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI2_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI3_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI4_PRIORITY 6 -#endif - -/** - * @brief EXTI9..5 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#endif - -/** - * @brief EXTI15..10 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI16_PRIORITY 6 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI17_PRIORITY 6 -#endif - -/** - * @brief EXTI18 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI18_PRIORITY 6 -#endif - -/** - * @brief EXTI19 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI19_PRIORITY 6 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/stm32_isr.h + * @brief STM32F3xx ISR handler header. + * + * @addtogroup STM32F1xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 +#define STM32_CAN2_TX_HANDLER Vector13C +#define STM32_CAN2_RX0_HANDLER Vector140 +#define STM32_CAN2_RX1_HANDLER Vector144 +#define STM32_CAN2_SCE_HANDLER Vector148 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 +#define STM32_CAN2_TX_NUMBER 63 +#define STM32_CAN2_RX0_NUMBER 64 +#define STM32_CAN2_RX1_NUMBER 65 +#define STM32_CAN2_SCE_NUMBER 66 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 + +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 + +/* + * OTG units. + */ +#define STM32_OTG1_HANDLER Vector14C + +#define STM32_OTG1_NUMBER 67 + +/* + * SDIO unit. + */ +#define STM32_SDIO_HANDLER Vector104 + +#define STM32_SDIO_NUMBER 49 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER VectorA4 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_CC_HANDLER VectorF8 +#define STM32_TIM9_HANDLER VectorA0 /* Note: same as STM32_TIM1_BRK */ +#define STM32_TIM10_HANDLER VectorA4 /* Note: same as STM32_TIM1_UP */ +#define STM32_TIM11_HANDLER VectorA8 /* Note: same as STM32_TIM1_TRG_COM */ +#define STM32_TIM12_HANDLER VectorEC /* Note: same as STM32_TIM8_BRK */ +#define STM32_TIM13_HANDLER VectorF0 /* Note: same as STM32_TIM8_UP */ +#define STM32_TIM14_HANDLER VectorF4 /* Note: same as STM32_TIM8_TRG_COM */ + +#define STM32_TIM1_UP_NUMBER 25 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_CC_NUMBER 46 +#define STM32_TIM9_NUMBER 24 /* Note: same as STM32_TIM1_BRK */ +#define STM32_TIM10_NUMBER 25 /* Note: same as STM32_TIM1_UP */ +#define STM32_TIM11_NUMBER 26 /* Note: same as STM32_TIM1_TRG_COM */ +#define STM32_TIM12_NUMBER 43 /* Note: same as STM32_TIM8_BRK */ +#define STM32_TIM13_NUMBER 44 /* Note: same as STM32_TIM8_UP */ +#define STM32_TIM14_NUMBER 45 /* Note: same as STM32_TIM8_TRG_COM */ + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 + +/* + * USB units. + */ +#define STM32_USB1_HP_HANDLER Vector8C +#define STM32_USB1_LP_HANDLER Vector90 + +#define STM32_USB1_HP_NUMBER 19 +#define STM32_USB1_LP_NUMBER 20 + +/* + * RTC unit + */ +#define STM32_RTC1_HANDLER Vector4C + +#define STM32_RTC1_NUMBER 3 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI0_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI1_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI2_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI3_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI4_PRIORITY 6 +#endif + +/** + * @brief EXTI9..5 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#endif + +/** + * @brief EXTI15..10 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI16_PRIORITY 6 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI17_PRIORITY 6 +#endif + +/** + * @brief EXTI18 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI18_PRIORITY 6 +#endif + +/** + * @brief EXTI19 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI19_PRIORITY 6 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/stm32_rcc.h b/os/hal/ports/STM32/STM32F1xx/stm32_rcc.h index 9578bf1453..67a0841ac5 100644 --- a/os/hal/ports/STM32/STM32F1xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32F1xx/stm32_rcc.h @@ -1,1230 +1,1230 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f10x.h. - * - * @addtogroup STM32F1xx_RCC - * @{ - */ - -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1(mask, lp) { \ - RCC->APB1ENR |= (mask); \ - (void)RCC->APB1ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - (void)RCC->APB1ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB2 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB2(mask, lp) { \ - RCC->APB2ENR |= (mask); \ - (void)RCC->APB2ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - (void)RCC->APB2ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) -/** @} */ - -/** - * @name Backup domain interface specific RCC operations - * @{ - */ -/** - * @brief Enables the BKP interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableBKPInterface(lp) rccEnableAPB1((RCC_APB1ENR_BKPEN), lp) - -/** - * @brief Disables BKP interface clock. - * - * @api - */ -#define rccDisableBKPInterface() rccDisableAPB1(RCC_APB1ENR_BKPEN) - -/** - * @brief Resets the Backup Domain interface. - * - * @api - */ -#define rccResetBKPInterface() rccResetAPB1(RCC_APB1ENR_BKPRST) - -/** - * @brief Resets the entire Backup Domain. - * - * @api - */ -#define rccResetBKP() (RCC->BDCR |= RCC_BDCR_BDRST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CAN1EN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) - -/** - * @brief Enables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) - -/** - * @brief Disables the CAN2 peripheral clock. - * - * @api - */ -#define rccDisableCAN2() rccDisableAPB1(RCC_APB1ENR_CAN2EN) - -/** - * @brief Resets the CAN2 peripheral. - * - * @api - */ -#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) -/** @} */ - -/** - * @name DMA peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetDMA1() - -/** - * @brief Enables the DMA2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) - -/** - * @brief Resets the DMA1 peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetDMA2() -/** @} */ - -/** - * @name ETH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the ETH peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableETH(lp) rccEnableAHB(RCC_AHBENR_ETHMACEN | \ - RCC_AHBENR_ETHMACTXEN | \ - RCC_AHBENR_ETHMACRXEN, lp) - -/** - * @brief Disables the ETH peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableETH() rccDisableAHB(RCC_AHBENR_ETHMACEN | \ - RCC_AHBENR_ETHMACTXEN | \ - RCC_AHBENR_ETHMACRXEN) - -/** - * @brief Resets the ETH peripheral. - * - * @api - */ -#define rccResetETH() rccResetAHB(RCC_AHBRSTR_ETHMACRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_FS(lp) rccEnableAHB(RCC_AHBENR_OTGFSEN, lp) - -/** - * @brief Disables the OTG_FS peripheral clock. - * - * @api - */ -#define rccDisableOTG_FS() rccDisableAHB(RCC_AHBENR_OTGFSEN) - -/** - * @brief Resets the OTG_FS peripheral. - * - * @api - */ -#define rccResetOTG_FS() rccResetAHB(RCC_AHBRSTR_OTGFSRST) -/** @} */ - -/** - * @name SDIO peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDIO peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDIO(lp) rccEnableAHB(RCC_AHBENR_SDIOEN, lp) - -/** - * @brief Disables the SDIO peripheral clock. - * - * @api - */ -#define rccDisableSDIO() rccDisableAHB(RCC_AHBENR_SDIOEN) - -/** - * @brief Resets the SDIO peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetSDIO() -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @brief Resets the SPI1 peripheral. - * - * @api - */ -#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) - -/** - * @brief Enables the SPI2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @brief Resets the TIM1 peripheral. - * - * @api - */ -#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) - -/** - * @brief Enables the TIM2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - - * @brief Enables the TIM9 peripheral clock. - - * @note The @p lp parameter is ignored in this family. - - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) - -/** - * @brief Disables the TIM9 peripheral clock. - * - * @api - */ -#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) - -/** - * @brief Resets the TIM9 peripheral. - * - * @api - */ -#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) - -/** - * @brief Enables the TIM10 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) - -/** - * @brief Disables the TIM10 peripheral clock. - * - * @api - */ -#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) - -/** - * @brief Resets the TIM10 peripheral. - * - * @api - */ -#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) - -/** - * @brief Enables the TIM11 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) - -/** - * @brief Disables the TIM11 peripheral clock. - * - * @api - */ -#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) - -/** - * @brief Resets the TIM11 peripheral. - * - * @api - */ -#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) - -/** - * @brief Enables the TIM12 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) - -/** - * @brief Disables the TIM12 peripheral clock. - * - * @api - */ -#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) - -/** - * @brief Resets the TIM12 peripheral. - * - * @api - */ -#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) - -/** - * @brief Enables the TIM13 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) - -/** - * @brief Disables the TIM13 peripheral clock. - * - * @api - */ -#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) - -/** - * @brief Resets the TIM13 peripheral. - * - * @api - */ -#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) - -/** - * @brief Enables the USART2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @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. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFSMC(lp) rccEnableAHB(RCC_AHBENR_FSMCEN, lp) - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#define rccDisableFSMC() rccDisableAHB(RCC_AHBENR_FSMCEN) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f10x.h. + * + * @addtogroup STM32F1xx_RCC + * @{ + */ + +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1(mask, lp) { \ + RCC->APB1ENR |= (mask); \ + (void)RCC->APB1ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + (void)RCC->APB1ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB2 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB2(mask, lp) { \ + RCC->APB2ENR |= (mask); \ + (void)RCC->APB2ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + (void)RCC->APB2ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) +/** @} */ + +/** + * @name Backup domain interface specific RCC operations + * @{ + */ +/** + * @brief Enables the BKP interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableBKPInterface(lp) rccEnableAPB1((RCC_APB1ENR_BKPEN), lp) + +/** + * @brief Disables BKP interface clock. + * + * @api + */ +#define rccDisableBKPInterface() rccDisableAPB1(RCC_APB1ENR_BKPEN) + +/** + * @brief Resets the Backup Domain interface. + * + * @api + */ +#define rccResetBKPInterface() rccResetAPB1(RCC_APB1ENR_BKPRST) + +/** + * @brief Resets the entire Backup Domain. + * + * @api + */ +#define rccResetBKP() (RCC->BDCR |= RCC_BDCR_BDRST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CAN1EN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) + +/** + * @brief Enables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) + +/** + * @brief Disables the CAN2 peripheral clock. + * + * @api + */ +#define rccDisableCAN2() rccDisableAPB1(RCC_APB1ENR_CAN2EN) + +/** + * @brief Resets the CAN2 peripheral. + * + * @api + */ +#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) +/** @} */ + +/** + * @name DMA peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetDMA1() + +/** + * @brief Enables the DMA2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) + +/** + * @brief Resets the DMA1 peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetDMA2() +/** @} */ + +/** + * @name ETH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the ETH peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableETH(lp) rccEnableAHB(RCC_AHBENR_ETHMACEN | \ + RCC_AHBENR_ETHMACTXEN | \ + RCC_AHBENR_ETHMACRXEN, lp) + +/** + * @brief Disables the ETH peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableETH() rccDisableAHB(RCC_AHBENR_ETHMACEN | \ + RCC_AHBENR_ETHMACTXEN | \ + RCC_AHBENR_ETHMACRXEN) + +/** + * @brief Resets the ETH peripheral. + * + * @api + */ +#define rccResetETH() rccResetAHB(RCC_AHBRSTR_ETHMACRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_FS(lp) rccEnableAHB(RCC_AHBENR_OTGFSEN, lp) + +/** + * @brief Disables the OTG_FS peripheral clock. + * + * @api + */ +#define rccDisableOTG_FS() rccDisableAHB(RCC_AHBENR_OTGFSEN) + +/** + * @brief Resets the OTG_FS peripheral. + * + * @api + */ +#define rccResetOTG_FS() rccResetAHB(RCC_AHBRSTR_OTGFSRST) +/** @} */ + +/** + * @name SDIO peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDIO peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDIO(lp) rccEnableAHB(RCC_AHBENR_SDIOEN, lp) + +/** + * @brief Disables the SDIO peripheral clock. + * + * @api + */ +#define rccDisableSDIO() rccDisableAHB(RCC_AHBENR_SDIOEN) + +/** + * @brief Resets the SDIO peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetSDIO() +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @brief Resets the SPI1 peripheral. + * + * @api + */ +#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) + +/** + * @brief Enables the SPI2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @brief Resets the TIM1 peripheral. + * + * @api + */ +#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) + +/** + * @brief Enables the TIM2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + + * @brief Enables the TIM9 peripheral clock. + + * @note The @p lp parameter is ignored in this family. + + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) + +/** + * @brief Disables the TIM9 peripheral clock. + * + * @api + */ +#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) + +/** + * @brief Resets the TIM9 peripheral. + * + * @api + */ +#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) + +/** + * @brief Enables the TIM10 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) + +/** + * @brief Disables the TIM10 peripheral clock. + * + * @api + */ +#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) + +/** + * @brief Resets the TIM10 peripheral. + * + * @api + */ +#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) + +/** + * @brief Enables the TIM11 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) + +/** + * @brief Disables the TIM11 peripheral clock. + * + * @api + */ +#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) + +/** + * @brief Resets the TIM11 peripheral. + * + * @api + */ +#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) + +/** + * @brief Enables the TIM12 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) + +/** + * @brief Disables the TIM12 peripheral clock. + * + * @api + */ +#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) + +/** + * @brief Resets the TIM12 peripheral. + * + * @api + */ +#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) + +/** + * @brief Enables the TIM13 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) + +/** + * @brief Disables the TIM13 peripheral clock. + * + * @api + */ +#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) + +/** + * @brief Resets the TIM13 peripheral. + * + * @api + */ +#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) + +/** + * @brief Enables the USART2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @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. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFSMC(lp) rccEnableAHB(RCC_AHBENR_FSMCEN, lp) + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#define rccDisableFSMC() rccDisableAHB(RCC_AHBENR_FSMCEN) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F1xx/stm32_registry.h b/os/hal/ports/STM32/STM32F1xx/stm32_registry.h index e06ed276ce..b5dbc2aa59 100644 --- a/os/hal/ports/STM32/STM32F1xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32F1xx/stm32_registry.h @@ -1,1422 +1,1422 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F1xx/stm32_registry.h - * @brief STM32F1xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -#if defined(STM32F100xB) -#define STM32F10X_MD_VL - -#elif defined(STM32F100xE) -#define STM32F10X_HD_VL - -#elif defined(STM32F101x6) || defined(STM32F102x6) || defined(STM32F103x6) -#define STM32F10X_LD - -#elif defined(STM32F101xB) || defined(STM32F102xB) || defined(STM32F103xB) -#define STM32F10X_MD - -#elif defined(STM32F101xE) || defined(STM32F103xE) -#define STM32F10X_HD - -#elif defined(STM32F101xG) || defined(STM32F103xG) -#define STM32F10X_XL - -#elif defined(STM32F105xC) || defined(STM32F107xC) -#define STM32F10X_CL - -#else -#error "unsupported or unrecognized STM32F1xx member" -#endif - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -#if defined(STM32F10X_MD_VL) || defined(__DOXYGEN__) -/** - * @name STM32F100 MD capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 0 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 19 -#define STM32_EXTI_IMR_MASK 0x00000000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#define STM32_FLASH_SECTOR_SIZE 1024U -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 32 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_UART9 FALSE -#define STM32_HAS_UART10 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE -/** @} */ -#endif /* defined(STM32F10X_MD_VL) */ - -#if defined(STM32F10X_LD) || defined(__DOXYGEN__) -/** - * @name STM32F103 LD capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 19 -#define STM32_EXTI_IMR_MASK 0x00000000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#define STM32_FLASH_SECTOR_SIZE 1024U -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 32 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_UART9 FALSE -#define STM32_HAS_UART10 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#if defined(STM32F103x6) -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#else -#define STM32_HAS_USB FALSE -#endif -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE -/** @} */ -#endif /* defined(STM32F10X_LD) */ - -#if defined(STM32F10X_MD) || defined(__DOXYGEN__) -/** - * @name STM32F103 MD capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 19 -#define STM32_EXTI_IMR_MASK 0x00000000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#define STM32_FLASH_SECTOR_SIZE 1024U -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_UART9 FALSE -#define STM32_HAS_UART10 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#if defined(STM32F103xB) -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#else -#define STM32_HAS_USB FALSE -#endif -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE -/** @} */ -#endif /* defined(STM32F10X_MD) */ - -#if defined(STM32F10X_HD) || defined(__DOXYGEN__) -/** - * @name STM32F103 HD capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 TRUE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH45_HANDLER Vector12C -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH45_NUMBER 59 - -#define STM32_DMA2_CH4_NUMBER STM32_DMA2_CH45_NUMBER -#define STM32_DMA2_CH5_NUMBER STM32_DMA2_CH45_NUMBER -#define DMA2_CH4_CMASK 0x00000C00U -#define DMA2_CH5_CMASK 0x00000C00U - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 19 -#define STM32_EXTI_IMR_MASK 0x00000000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#define STM32_FLASH_SECTOR_SIZE 2048U -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS FALSE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 4 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_UART9 FALSE -#define STM32_HAS_UART10 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC FALSE -#define STM32_FSMC_HANDLER Vector100 -#define STM32_FSMC_NUMBER 48 - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE -/** @} */ -#endif /* defined(STM32F10X_HD) */ - -#if defined(STM32F10X_XL) || defined(__DOXYGEN__) -/** - * @name STM32F103 XL capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 TRUE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 19 -#define STM32_EXTI_IMR_MASK 0x00000000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 -#define STM32_FLASH_SECTOR_SIZE 2048U -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS FALSE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_UART9 FALSE -#define STM32_HAS_UART10 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC FALSE -#define STM32_FSMC_HANDLER Vector100 -#define STM32_FSMC_NUMBER 48 - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE -/** @} */ -#endif /* defined(STM32F10X_XL) */ - -#if defined(STM32F10X_CL) || defined(__DOXYGEN__) -/** - * @name STM32F105/F107 CL capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE -#define STM32_ETH_HANDLER Vector134 -#define STM32_ETH_NUMBER 61 - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 20 -#define STM32_EXTI_IMR_MASK 0x00000000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#define STM32_FLASH_SECTOR_SIZE 2048U -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS FALSE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_UART9 FALSE -#define STM32_HAS_UART10 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 1 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 3 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE -/** @} */ -#endif /* defined(STM32F10X_CL) */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F1xx/stm32_registry.h + * @brief STM32F1xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +#if defined(STM32F100xB) +#define STM32F10X_MD_VL + +#elif defined(STM32F100xE) +#define STM32F10X_HD_VL + +#elif defined(STM32F101x6) || defined(STM32F102x6) || defined(STM32F103x6) +#define STM32F10X_LD + +#elif defined(STM32F101xB) || defined(STM32F102xB) || defined(STM32F103xB) +#define STM32F10X_MD + +#elif defined(STM32F101xE) || defined(STM32F103xE) +#define STM32F10X_HD + +#elif defined(STM32F101xG) || defined(STM32F103xG) +#define STM32F10X_XL + +#elif defined(STM32F105xC) || defined(STM32F107xC) +#define STM32F10X_CL + +#else +#error "unsupported or unrecognized STM32F1xx member" +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +#if defined(STM32F10X_MD_VL) || defined(__DOXYGEN__) +/** + * @name STM32F100 MD capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 0 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 19 +#define STM32_EXTI_IMR_MASK 0x00000000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#define STM32_FLASH_SECTOR_SIZE 1024U +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 32 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_UART9 FALSE +#define STM32_HAS_UART10 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE +/** @} */ +#endif /* defined(STM32F10X_MD_VL) */ + +#if defined(STM32F10X_LD) || defined(__DOXYGEN__) +/** + * @name STM32F103 LD capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 19 +#define STM32_EXTI_IMR_MASK 0x00000000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#define STM32_FLASH_SECTOR_SIZE 1024U +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 32 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_UART9 FALSE +#define STM32_HAS_UART10 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#if defined(STM32F103x6) +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#else +#define STM32_HAS_USB FALSE +#endif +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE +/** @} */ +#endif /* defined(STM32F10X_LD) */ + +#if defined(STM32F10X_MD) || defined(__DOXYGEN__) +/** + * @name STM32F103 MD capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 19 +#define STM32_EXTI_IMR_MASK 0x00000000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#define STM32_FLASH_SECTOR_SIZE 1024U +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_UART9 FALSE +#define STM32_HAS_UART10 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#if defined(STM32F103xB) +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#else +#define STM32_HAS_USB FALSE +#endif +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE +/** @} */ +#endif /* defined(STM32F10X_MD) */ + +#if defined(STM32F10X_HD) || defined(__DOXYGEN__) +/** + * @name STM32F103 HD capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 TRUE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH45_HANDLER Vector12C +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH45_NUMBER 59 + +#define STM32_DMA2_CH4_NUMBER STM32_DMA2_CH45_NUMBER +#define STM32_DMA2_CH5_NUMBER STM32_DMA2_CH45_NUMBER +#define DMA2_CH4_CMASK 0x00000C00U +#define DMA2_CH5_CMASK 0x00000C00U + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 19 +#define STM32_EXTI_IMR_MASK 0x00000000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#define STM32_FLASH_SECTOR_SIZE 2048U +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS FALSE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 4 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_UART9 FALSE +#define STM32_HAS_UART10 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC FALSE +#define STM32_FSMC_HANDLER Vector100 +#define STM32_FSMC_NUMBER 48 + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE +/** @} */ +#endif /* defined(STM32F10X_HD) */ + +#if defined(STM32F10X_XL) || defined(__DOXYGEN__) +/** + * @name STM32F103 XL capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 TRUE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 19 +#define STM32_EXTI_IMR_MASK 0x00000000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 +#define STM32_FLASH_SECTOR_SIZE 2048U +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS FALSE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_UART9 FALSE +#define STM32_HAS_UART10 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC FALSE +#define STM32_FSMC_HANDLER Vector100 +#define STM32_FSMC_NUMBER 48 + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE +/** @} */ +#endif /* defined(STM32F10X_XL) */ + +#if defined(STM32F10X_CL) || defined(__DOXYGEN__) +/** + * @name STM32F105/F107 CL capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE +#define STM32_ETH_HANDLER Vector134 +#define STM32_ETH_NUMBER 61 + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 20 +#define STM32_EXTI_IMR_MASK 0x00000000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#define STM32_FLASH_SECTOR_SIZE 2048U +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 128 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS FALSE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_UART9 FALSE +#define STM32_HAS_UART10 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 1 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 3 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE +/** @} */ +#endif /* defined(STM32F10X_CL) */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c b/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c index 1001eb86c1..0631b5e484 100644 --- a/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c +++ b/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c @@ -1,740 +1,740 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/hal_adc_lld.c - * @brief STM32F37x ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SDADC_FORBIDDEN_CR1_FLAGS (SDADC_CR1_INIT | SDADC_CR1_RDMAEN | \ - SDADC_CR1_RSYNC | SDADC_CR1_JSYNC | \ - SDADC_CR1_ROVRIE | SDADC_CR1_REOCIE | \ - SDADC_CR1_JEOCIE | SDADC_CR1_EOCALIE) - -#define SDADC_ENFORCED_CR1_FLAGS (SDADC_CR1_JDMAEN | SDADC_CR1_JOVRIE) - -#define SDADC_FORBIDDEN_CR2_FLAGS (SDADC_CR2_RSWSTART | \ - SDADC_CR2_RCONT | \ - SDADC_CR2_RCH | \ - SDADC_CR2_JCONT | \ - SDADC_CR2_STARTCALIB | \ - SDADC_CR2_CALIBCNT) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/** @brief SDADC1 driver identifier.*/ -#if STM32_ADC_USE_SDADC1 || defined(__DOXYGEN__) -ADCDriver SDADCD1; -#endif - -/** @brief SDADC2 driver identifier.*/ -#if STM32_ADC_USE_SDADC2 || defined(__DOXYGEN__) -ADCDriver SDADCD2; -#endif - -/** @brief SDADC3 driver identifier.*/ -#if STM32_ADC_USE_SDADC3 || defined(__DOXYGEN__) -ADCDriver SDADCD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const ADCConfig adc_lld_default_config = { -#if STM32_ADC_USE_SDADC - 0, - { - 0, - 0, - 0 - } -#else /* !STM32_ADC_USE_SDADC */ - 0 -#endif /* !STM32_ADC_USE_SDADC */ -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Stops, reconfigures and restarts an ADC/SDADC. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_reconfig(ADCDriver *adcp) { - -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - if (adcp->adc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC - { - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - uint32_t cr2 = adcp->adc->CR2 & ADC_CR2_TSVREFE; - adcp->adc->CR2 = cr2; - adcp->adc->CR1 = 0; - adcp->adc->CR2 = cr2 | ADC_CR2_ADON; - - } -#endif /* STM32_ADC_USE_ADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else if (adcp->sdadc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_SDADC - { - /* SDADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->sdadc->CR2 = 0; - adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & - ~SDADC_FORBIDDEN_CR1_FLAGS; - adcp->sdadc->CONF0R = (adcp->sdadc->CONF0R & SDADC_CONFR_OFFSET_MASK) | - adcp->config->confxr[0]; - adcp->sdadc->CONF1R = (adcp->sdadc->CONF1R & SDADC_CONFR_OFFSET_MASK) | - adcp->config->confxr[1]; - adcp->sdadc->CONF2R = (adcp->sdadc->CONF2R & SDADC_CONFR_OFFSET_MASK) | - adcp->config->confxr[2]; - adcp->sdadc->CR2 = SDADC_CR2_ADON; - } -#endif /* STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC -else { - osalDbgAssert(FALSE, "invalid state"); - } -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -} - -/** - * @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 - * - * @notapi - */ -static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} - -#if STM32_ADC_USE_ADC || defined(__DOXYGEN__) -/** - * @brief ADC ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] sr content of the ISR register - * - * @notapi - */ -static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t sr) { - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - if (sr & ADC_SR_AWD) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD1); - } - } -} -#endif /* STM32_ADC_USE_ADC */ - -#if STM32_ADC_USE_SDADC || defined(__DOXYGEN__) -/** - * @brief ADC ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] isr content of the ISR register - * - * @notapi - */ -static void sdadc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - /* 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 ((isr & SDADC_ISR_JOVRF) && - (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); - } - } -} -#endif /* STM32_ADC_USE_SDADC */ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -/** - * @brief ADC1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector88) { - uint32_t sr; - - OSAL_IRQ_PROLOGUE(); - - sr = ADC1->SR; - ADC1->SR = 0; - adc_lld_serve_interrupt(&ADCD1, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_SDADC1 || defined(__DOXYGEN__) -/** - * @brief SDADC1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector134) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = SDADC1->ISR; - SDADC1->CLRISR = isr; - sdadc_lld_serve_interrupt(&SDADCD1, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_SDADC1 */ - -#if STM32_ADC_USE_SDADC2 || defined(__DOXYGEN__) -/** - * @brief SDADC2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector138) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = SDADC2->ISR; - SDADC2->CLRISR = isr; - sdadc_lld_serve_interrupt(&SDADCD2, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_SDADC2 */ - -#if STM32_ADC_USE_SDADC3 || defined(__DOXYGEN__) -/** - * @brief SDADC3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector13C) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = SDADC3->ISR; - SDADC3->CLRISR = isr; - sdadc_lld_serve_interrupt(&SDADCD3, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_SDADC3 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; -#if STM32_ADC_USE_SDADC - ADCD1.sdadc = NULL; -#endif - ADCD1.dmastp = NULL; - 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; - nvicEnableVector(ADC1_IRQn, STM32_ADC_ADC1_IRQ_PRIORITY); -#endif - -#if STM32_ADC_USE_SDADC1 - /* Driver initialization.*/ - adcObjectInit(&SDADCD1); -#if STM32_ADC_USE_ADC - SDADCD1.adc = NULL; -#endif - SDADCD1.sdadc = SDADC1; - SDADCD1.dmastp = NULL; - SDADCD1.dmamode = STM32_DMA_CR_CHSEL(SDADC1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_SDADC1_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; - nvicEnableVector(SDADC1_IRQn, STM32_ADC_SDADC1_IRQ_PRIORITY); -#endif - -#if STM32_ADC_USE_SDADC2 - /* Driver initialization.*/ - adcObjectInit(&SDADCD2); -#if STM32_ADC_USE_ADC - SDADCD2.adc = NULL; -#endif - SDADCD2.sdadc = SDADC2; - SDADCD2.dmastp = NULL; - SDADCD2.dmamode = STM32_DMA_CR_CHSEL(SDADC2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_SDADC2_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; - nvicEnableVector(SDADC2_IRQn, STM32_ADC_SDADC2_IRQ_PRIORITY); -#endif - -#if STM32_ADC_USE_SDADC3 - /* Driver initialization.*/ - adcObjectInit(&SDADCD3); -#if STM32_ADC_USE_ADC - SDADCD3.adc = NULL; -#endif - SDADCD3.sdadc = SDADC3; - SDADCD3.dmastp = NULL; - SDADCD3.dmamode = STM32_DMA_CR_CHSEL(SDADC3_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_SDADC3_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; - nvicEnableVector(SDADC3_IRQn, STM32_ADC_SDADC3_IRQ_PRIORITY); -#endif -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - if (adcp->config == NULL) - adcp->config = &adc_lld_default_config; - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(1, 1), - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - rccEnableADC1(true); - } -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_SDADC1 - if (&SDADCD1 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(2, 3), - STM32_ADC_SDADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - dmaStreamSetPeripheral(adcp->dmastp, &SDADC1->JDATAR); - rccEnableSDADC1(true); - PWR->CR |= PWR_CR_SDADC1EN; - adcp->sdadc->CR2 = 0; - adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & - ~SDADC_FORBIDDEN_CR1_FLAGS; - adcp->sdadc->CR2 = SDADC_CR2_ADON; - } -#endif /* STM32_ADC_USE_SDADC1 */ - -#if STM32_ADC_USE_SDADC2 - if (&SDADCD2 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(2, 4), - STM32_ADC_SDADC2_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - dmaStreamSetPeripheral(adcp->dmastp, &SDADC2->JDATAR); - rccEnableSDADC2(true); - PWR->CR |= PWR_CR_SDADC2EN; - adcp->sdadc->CR2 = 0; - adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & - ~SDADC_FORBIDDEN_CR1_FLAGS; - adcp->sdadc->CR2 = SDADC_CR2_ADON; - } -#endif /* STM32_ADC_USE_SDADC2 */ - -#if STM32_ADC_USE_SDADC3 - if (&SDADCD3 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(2, 5), - STM32_ADC_SDADC3_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - dmaStreamSetPeripheral(adcp->dmastp, &SDADC3->JDATAR); - rccEnableSDADC3(true); - PWR->CR |= PWR_CR_SDADC3EN; - adcp->sdadc->CR2 = 0; - adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & - ~SDADC_FORBIDDEN_CR1_FLAGS; - adcp->sdadc->CR2 = SDADC_CR2_ADON; - } -#endif /* STM32_ADC_USE_SDADC3 */ - } - - adc_lld_reconfig(adcp); -} - -/** - * @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) { - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - rccDisableADC1(); - } -#endif - -#if STM32_ADC_USE_SDADC1 - if (&SDADCD1 == adcp) { - adcp->sdadc->CR1 = 0; - adcp->sdadc->CR2 = 0; - rccDisableSDADC1(); - PWR->CR &= ~PWR_CR_SDADC1EN; - } -#endif - -#if STM32_ADC_USE_SDADC2 - if (&SDADCD2 == adcp) { - adcp->sdadc->CR1 = 0; - adcp->sdadc->CR2 = 0; - rccDisableSDADC2(); - PWR->CR &= ~PWR_CR_SDADC2EN; - } -#endif - -#if STM32_ADC_USE_SDADC3 - if (&SDADCD3 == adcp) { - adcp->sdadc->CR1 = 0; - adcp->sdadc->CR2 = 0; - rccDisableSDADC3(); - PWR->CR &= ~PWR_CR_SDADC3EN; - } -#endif - } -} - -/** - * @brief Starts an ADC conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start_conversion(ADCDriver *adcp) { - uint32_t mode; - const ADCConversionGroup* grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, - (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - if (adcp->adc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC - { - uint32_t cr2 = adcp->adc->CR2 & ADC_CR2_TSVREFE; - cr2 |= grpp->u.adc.cr2 | ADC_CR2_DMA | ADC_CR2_ADON; - if ((cr2 & ADC_CR2_SWSTART) != 0) - cr2 |= ADC_CR2_CONT; - adcp->adc->CR2 = cr2; - - /* ADC setup.*/ - adcp->adc->SR = 0; - adcp->adc->LTR = grpp->u.adc.ltr; - adcp->adc->HTR = grpp->u.adc.htr; - adcp->adc->SMPR1 = grpp->u.adc.smpr[0]; - adcp->adc->SMPR2 = grpp->u.adc.smpr[1]; - adcp->adc->SQR1 = grpp->u.adc.sqr[0] | - ADC_SQR1_NUM_CH(grpp->num_channels); - adcp->adc->SQR2 = grpp->u.adc.sqr[1]; - adcp->adc->SQR3 = grpp->u.adc.sqr[2]; - - /* ADC conversion start, the start is performed using the method - specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/ - adcp->adc->CR1 = grpp->u.adc.cr1 | ADC_CR1_AWDIE | ADC_CR1_SCAN; - adcp->adc->CR2 = adcp->adc->CR2; /* Triggers the conversion start.*/ - } -#endif /* STM32_ADC_USE_ADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else if (adcp->sdadc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_SDADC - { - uint32_t cr2 = (grpp->u.sdadc.cr2 & ~SDADC_FORBIDDEN_CR2_FLAGS) | - SDADC_CR2_ADON; - if ((grpp->u.sdadc.cr2 & SDADC_CR2_JSWSTART) != 0) - cr2 |= SDADC_CR2_JCONT; - - /* Entering initialization mode.*/ - adcp->sdadc->CR1 |= SDADC_CR1_INIT; - while ((adcp->sdadc->ISR & SDADC_ISR_INITRDY) == 0) - ; - - /* SDADC setup.*/ - adcp->sdadc->JCHGR = grpp->u.sdadc.jchgr; - adcp->sdadc->CONFCHR1 = grpp->u.sdadc.confchr[0]; - adcp->sdadc->CONFCHR2 = grpp->u.sdadc.confchr[1]; - - /* SDADC trigger modes, this write must be performed when - SDADC_CR1_INIT=1.*/ - adcp->sdadc->CR2 = cr2; - - /* Leaving initialization mode.*/ - adcp->sdadc->CR1 &= ~SDADC_CR1_INIT; - - /* Special case, if SDADC_CR2_JSWSTART is specified it has to be - written after SDADC_CR1_INIT has been set to zero. Just a write is - performed, any other bit is ingore if not in initialization mode.*/ - adcp->sdadc->CR2 = cr2; - } -#endif /* STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else { - osalDbgAssert(FALSE, "invalid state"); - } -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop_conversion(ADCDriver *adcp) { - - /* Disabling the associated DMA stream.*/ - dmaStreamDisable(adcp->dmastp); - - /* Stopping and restarting the whole ADC, apparently the only way to stop - a conversion.*/ - adc_lld_reconfig(adcp); -} - -/** - * @brief Calibrates an ADC unit. - * @note The calibration must be performed after calling @p adcStart(). - * @note For SDADC units it is assumed that the field SDADC_CR2_CALIBCNT - * has been - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcSTM32Calibrate(ADCDriver *adcp) { - - osalDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_COMPLETE) || - (adcp->state == ADC_ERROR), - "not ready"); - -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - if (adcp->adc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC - { - /* Resetting calibration just to be safe.*/ - ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; - while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0) - ; - - /* Calibration.*/ - ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL; - while ((ADC1->CR2 & ADC_CR2_CAL) != 0) - ; - } -#endif /* STM32_ADC_USE_ADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else if (adcp->sdadc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_SDADC - { - /* Selecting a full calibration in three steps.*/ - adcp->sdadc->CR2 = (adcp->sdadc->CR2 & ~SDADC_CR2_CALIBCNT) | - SDADC_CR2_CALIBCNT_1; - - /* Calibration.*/ - adcp->sdadc->CR2 |= SDADC_CR2_STARTCALIB; - while ((adcp->sdadc->ISR & SDADC_ISR_EOCALF) == 0) - ; - - /* Clearing the EOCALF flag.*/ - adcp->sdadc->CLRISR |= SDADC_ISR_CLREOCALF; - } -#endif /* STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else { - osalDbgAssert(FALSE, "invalid state"); - } -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -} - -#if STM32_ADC_USE_ADC || defined(__DOXYGEN__) -/** - * @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. - * - * @api - */ -void adcSTM32EnableTSVREFE(void) { - - ADC1->CR2 |= ADC_CR2_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. - * - * @api - */ -void adcSTM32DisableTSVREFE(void) { - - ADC1->CR2 &= ~ADC_CR2_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. - * - * @api - */ -void adcSTM32EnableVBATE(void) { - - SYSCFG->CFGR1 |= SYSCFG_CFGR1_VBAT; -} - -/** - * @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. - * - * @api - */ -void adcSTM32DisableVBATE(void) { - - SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_VBAT; -} -#endif /* STM32_ADC_USE_ADC */ - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/hal_adc_lld.c + * @brief STM32F37x ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SDADC_FORBIDDEN_CR1_FLAGS (SDADC_CR1_INIT | SDADC_CR1_RDMAEN | \ + SDADC_CR1_RSYNC | SDADC_CR1_JSYNC | \ + SDADC_CR1_ROVRIE | SDADC_CR1_REOCIE | \ + SDADC_CR1_JEOCIE | SDADC_CR1_EOCALIE) + +#define SDADC_ENFORCED_CR1_FLAGS (SDADC_CR1_JDMAEN | SDADC_CR1_JOVRIE) + +#define SDADC_FORBIDDEN_CR2_FLAGS (SDADC_CR2_RSWSTART | \ + SDADC_CR2_RCONT | \ + SDADC_CR2_RCH | \ + SDADC_CR2_JCONT | \ + SDADC_CR2_STARTCALIB | \ + SDADC_CR2_CALIBCNT) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/** @brief SDADC1 driver identifier.*/ +#if STM32_ADC_USE_SDADC1 || defined(__DOXYGEN__) +ADCDriver SDADCD1; +#endif + +/** @brief SDADC2 driver identifier.*/ +#if STM32_ADC_USE_SDADC2 || defined(__DOXYGEN__) +ADCDriver SDADCD2; +#endif + +/** @brief SDADC3 driver identifier.*/ +#if STM32_ADC_USE_SDADC3 || defined(__DOXYGEN__) +ADCDriver SDADCD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const ADCConfig adc_lld_default_config = { +#if STM32_ADC_USE_SDADC + 0, + { + 0, + 0, + 0 + } +#else /* !STM32_ADC_USE_SDADC */ + 0 +#endif /* !STM32_ADC_USE_SDADC */ +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Stops, reconfigures and restarts an ADC/SDADC. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_reconfig(ADCDriver *adcp) { + +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + if (adcp->adc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC + { + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + uint32_t cr2 = adcp->adc->CR2 & ADC_CR2_TSVREFE; + adcp->adc->CR2 = cr2; + adcp->adc->CR1 = 0; + adcp->adc->CR2 = cr2 | ADC_CR2_ADON; + + } +#endif /* STM32_ADC_USE_ADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + else if (adcp->sdadc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_SDADC + { + /* SDADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->sdadc->CR2 = 0; + adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & + ~SDADC_FORBIDDEN_CR1_FLAGS; + adcp->sdadc->CONF0R = (adcp->sdadc->CONF0R & SDADC_CONFR_OFFSET_MASK) | + adcp->config->confxr[0]; + adcp->sdadc->CONF1R = (adcp->sdadc->CONF1R & SDADC_CONFR_OFFSET_MASK) | + adcp->config->confxr[1]; + adcp->sdadc->CONF2R = (adcp->sdadc->CONF2R & SDADC_CONFR_OFFSET_MASK) | + adcp->config->confxr[2]; + adcp->sdadc->CR2 = SDADC_CR2_ADON; + } +#endif /* STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC +else { + osalDbgAssert(FALSE, "invalid state"); + } +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +} + +/** + * @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 + * + * @notapi + */ +static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} + +#if STM32_ADC_USE_ADC || defined(__DOXYGEN__) +/** + * @brief ADC ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] sr content of the ISR register + * + * @notapi + */ +static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t sr) { + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + if (sr & ADC_SR_AWD) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD1); + } + } +} +#endif /* STM32_ADC_USE_ADC */ + +#if STM32_ADC_USE_SDADC || defined(__DOXYGEN__) +/** + * @brief ADC ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] isr content of the ISR register + * + * @notapi + */ +static void sdadc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + /* 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 ((isr & SDADC_ISR_JOVRF) && + (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); + } + } +} +#endif /* STM32_ADC_USE_SDADC */ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +/** + * @brief ADC1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector88) { + uint32_t sr; + + OSAL_IRQ_PROLOGUE(); + + sr = ADC1->SR; + ADC1->SR = 0; + adc_lld_serve_interrupt(&ADCD1, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_SDADC1 || defined(__DOXYGEN__) +/** + * @brief SDADC1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector134) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = SDADC1->ISR; + SDADC1->CLRISR = isr; + sdadc_lld_serve_interrupt(&SDADCD1, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_SDADC1 */ + +#if STM32_ADC_USE_SDADC2 || defined(__DOXYGEN__) +/** + * @brief SDADC2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector138) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = SDADC2->ISR; + SDADC2->CLRISR = isr; + sdadc_lld_serve_interrupt(&SDADCD2, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_SDADC2 */ + +#if STM32_ADC_USE_SDADC3 || defined(__DOXYGEN__) +/** + * @brief SDADC3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector13C) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = SDADC3->ISR; + SDADC3->CLRISR = isr; + sdadc_lld_serve_interrupt(&SDADCD3, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_SDADC3 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; +#if STM32_ADC_USE_SDADC + ADCD1.sdadc = NULL; +#endif + ADCD1.dmastp = NULL; + 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; + nvicEnableVector(ADC1_IRQn, STM32_ADC_ADC1_IRQ_PRIORITY); +#endif + +#if STM32_ADC_USE_SDADC1 + /* Driver initialization.*/ + adcObjectInit(&SDADCD1); +#if STM32_ADC_USE_ADC + SDADCD1.adc = NULL; +#endif + SDADCD1.sdadc = SDADC1; + SDADCD1.dmastp = NULL; + SDADCD1.dmamode = STM32_DMA_CR_CHSEL(SDADC1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_SDADC1_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; + nvicEnableVector(SDADC1_IRQn, STM32_ADC_SDADC1_IRQ_PRIORITY); +#endif + +#if STM32_ADC_USE_SDADC2 + /* Driver initialization.*/ + adcObjectInit(&SDADCD2); +#if STM32_ADC_USE_ADC + SDADCD2.adc = NULL; +#endif + SDADCD2.sdadc = SDADC2; + SDADCD2.dmastp = NULL; + SDADCD2.dmamode = STM32_DMA_CR_CHSEL(SDADC2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_SDADC2_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; + nvicEnableVector(SDADC2_IRQn, STM32_ADC_SDADC2_IRQ_PRIORITY); +#endif + +#if STM32_ADC_USE_SDADC3 + /* Driver initialization.*/ + adcObjectInit(&SDADCD3); +#if STM32_ADC_USE_ADC + SDADCD3.adc = NULL; +#endif + SDADCD3.sdadc = SDADC3; + SDADCD3.dmastp = NULL; + SDADCD3.dmamode = STM32_DMA_CR_CHSEL(SDADC3_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_SDADC3_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; + nvicEnableVector(SDADC3_IRQn, STM32_ADC_SDADC3_IRQ_PRIORITY); +#endif +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + if (adcp->config == NULL) + adcp->config = &adc_lld_default_config; + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(1, 1), + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + rccEnableADC1(true); + } +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_SDADC1 + if (&SDADCD1 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(2, 3), + STM32_ADC_SDADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + dmaStreamSetPeripheral(adcp->dmastp, &SDADC1->JDATAR); + rccEnableSDADC1(true); + PWR->CR |= PWR_CR_SDADC1EN; + adcp->sdadc->CR2 = 0; + adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & + ~SDADC_FORBIDDEN_CR1_FLAGS; + adcp->sdadc->CR2 = SDADC_CR2_ADON; + } +#endif /* STM32_ADC_USE_SDADC1 */ + +#if STM32_ADC_USE_SDADC2 + if (&SDADCD2 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(2, 4), + STM32_ADC_SDADC2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + dmaStreamSetPeripheral(adcp->dmastp, &SDADC2->JDATAR); + rccEnableSDADC2(true); + PWR->CR |= PWR_CR_SDADC2EN; + adcp->sdadc->CR2 = 0; + adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & + ~SDADC_FORBIDDEN_CR1_FLAGS; + adcp->sdadc->CR2 = SDADC_CR2_ADON; + } +#endif /* STM32_ADC_USE_SDADC2 */ + +#if STM32_ADC_USE_SDADC3 + if (&SDADCD3 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(2, 5), + STM32_ADC_SDADC3_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + dmaStreamSetPeripheral(adcp->dmastp, &SDADC3->JDATAR); + rccEnableSDADC3(true); + PWR->CR |= PWR_CR_SDADC3EN; + adcp->sdadc->CR2 = 0; + adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & + ~SDADC_FORBIDDEN_CR1_FLAGS; + adcp->sdadc->CR2 = SDADC_CR2_ADON; + } +#endif /* STM32_ADC_USE_SDADC3 */ + } + + adc_lld_reconfig(adcp); +} + +/** + * @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) { + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + rccDisableADC1(); + } +#endif + +#if STM32_ADC_USE_SDADC1 + if (&SDADCD1 == adcp) { + adcp->sdadc->CR1 = 0; + adcp->sdadc->CR2 = 0; + rccDisableSDADC1(); + PWR->CR &= ~PWR_CR_SDADC1EN; + } +#endif + +#if STM32_ADC_USE_SDADC2 + if (&SDADCD2 == adcp) { + adcp->sdadc->CR1 = 0; + adcp->sdadc->CR2 = 0; + rccDisableSDADC2(); + PWR->CR &= ~PWR_CR_SDADC2EN; + } +#endif + +#if STM32_ADC_USE_SDADC3 + if (&SDADCD3 == adcp) { + adcp->sdadc->CR1 = 0; + adcp->sdadc->CR2 = 0; + rccDisableSDADC3(); + PWR->CR &= ~PWR_CR_SDADC3EN; + } +#endif + } +} + +/** + * @brief Starts an ADC conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start_conversion(ADCDriver *adcp) { + uint32_t mode; + const ADCConversionGroup* grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, + (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + if (adcp->adc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC + { + uint32_t cr2 = adcp->adc->CR2 & ADC_CR2_TSVREFE; + cr2 |= grpp->u.adc.cr2 | ADC_CR2_DMA | ADC_CR2_ADON; + if ((cr2 & ADC_CR2_SWSTART) != 0) + cr2 |= ADC_CR2_CONT; + adcp->adc->CR2 = cr2; + + /* ADC setup.*/ + adcp->adc->SR = 0; + adcp->adc->LTR = grpp->u.adc.ltr; + adcp->adc->HTR = grpp->u.adc.htr; + adcp->adc->SMPR1 = grpp->u.adc.smpr[0]; + adcp->adc->SMPR2 = grpp->u.adc.smpr[1]; + adcp->adc->SQR1 = grpp->u.adc.sqr[0] | + ADC_SQR1_NUM_CH(grpp->num_channels); + adcp->adc->SQR2 = grpp->u.adc.sqr[1]; + adcp->adc->SQR3 = grpp->u.adc.sqr[2]; + + /* ADC conversion start, the start is performed using the method + specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/ + adcp->adc->CR1 = grpp->u.adc.cr1 | ADC_CR1_AWDIE | ADC_CR1_SCAN; + adcp->adc->CR2 = adcp->adc->CR2; /* Triggers the conversion start.*/ + } +#endif /* STM32_ADC_USE_ADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + else if (adcp->sdadc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_SDADC + { + uint32_t cr2 = (grpp->u.sdadc.cr2 & ~SDADC_FORBIDDEN_CR2_FLAGS) | + SDADC_CR2_ADON; + if ((grpp->u.sdadc.cr2 & SDADC_CR2_JSWSTART) != 0) + cr2 |= SDADC_CR2_JCONT; + + /* Entering initialization mode.*/ + adcp->sdadc->CR1 |= SDADC_CR1_INIT; + while ((adcp->sdadc->ISR & SDADC_ISR_INITRDY) == 0) + ; + + /* SDADC setup.*/ + adcp->sdadc->JCHGR = grpp->u.sdadc.jchgr; + adcp->sdadc->CONFCHR1 = grpp->u.sdadc.confchr[0]; + adcp->sdadc->CONFCHR2 = grpp->u.sdadc.confchr[1]; + + /* SDADC trigger modes, this write must be performed when + SDADC_CR1_INIT=1.*/ + adcp->sdadc->CR2 = cr2; + + /* Leaving initialization mode.*/ + adcp->sdadc->CR1 &= ~SDADC_CR1_INIT; + + /* Special case, if SDADC_CR2_JSWSTART is specified it has to be + written after SDADC_CR1_INIT has been set to zero. Just a write is + performed, any other bit is ingore if not in initialization mode.*/ + adcp->sdadc->CR2 = cr2; + } +#endif /* STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + else { + osalDbgAssert(FALSE, "invalid state"); + } +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + + /* Disabling the associated DMA stream.*/ + dmaStreamDisable(adcp->dmastp); + + /* Stopping and restarting the whole ADC, apparently the only way to stop + a conversion.*/ + adc_lld_reconfig(adcp); +} + +/** + * @brief Calibrates an ADC unit. + * @note The calibration must be performed after calling @p adcStart(). + * @note For SDADC units it is assumed that the field SDADC_CR2_CALIBCNT + * has been + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcSTM32Calibrate(ADCDriver *adcp) { + + osalDbgAssert((adcp->state == ADC_READY) || + (adcp->state == ADC_COMPLETE) || + (adcp->state == ADC_ERROR), + "not ready"); + +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + if (adcp->adc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC + { + /* Resetting calibration just to be safe.*/ + ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; + while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0) + ; + + /* Calibration.*/ + ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL; + while ((ADC1->CR2 & ADC_CR2_CAL) != 0) + ; + } +#endif /* STM32_ADC_USE_ADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + else if (adcp->sdadc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_SDADC + { + /* Selecting a full calibration in three steps.*/ + adcp->sdadc->CR2 = (adcp->sdadc->CR2 & ~SDADC_CR2_CALIBCNT) | + SDADC_CR2_CALIBCNT_1; + + /* Calibration.*/ + adcp->sdadc->CR2 |= SDADC_CR2_STARTCALIB; + while ((adcp->sdadc->ISR & SDADC_ISR_EOCALF) == 0) + ; + + /* Clearing the EOCALF flag.*/ + adcp->sdadc->CLRISR |= SDADC_ISR_CLREOCALF; + } +#endif /* STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + else { + osalDbgAssert(FALSE, "invalid state"); + } +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +} + +#if STM32_ADC_USE_ADC || defined(__DOXYGEN__) +/** + * @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. + * + * @api + */ +void adcSTM32EnableTSVREFE(void) { + + ADC1->CR2 |= ADC_CR2_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. + * + * @api + */ +void adcSTM32DisableTSVREFE(void) { + + ADC1->CR2 &= ~ADC_CR2_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. + * + * @api + */ +void adcSTM32EnableVBATE(void) { + + SYSCFG->CFGR1 |= SYSCFG_CFGR1_VBAT; +} + +/** + * @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. + * + * @api + */ +void adcSTM32DisableVBATE(void) { + + SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_VBAT; +} +#endif /* STM32_ADC_USE_ADC */ + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/hal_adc_lld.h b/os/hal/ports/STM32/STM32F37x/hal_adc_lld.h index 055883a039..dceeaba71f 100644 --- a/os/hal/ports/STM32/STM32F37x/hal_adc_lld.h +++ b/os/hal/ports/STM32/STM32F37x/hal_adc_lld.h @@ -1,639 +1,639 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/hal_adc_lld.h - * @brief STM32F37x ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Triggers selection - * @{ - */ -#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @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.*/ -#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ -#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */ -#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */ -#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */ -#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */ -#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */ -#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */ -#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */ -#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */ -/** @} */ - -/** - * @name SDADC JCHGR bit definitions - * @{ - */ -#define SDADC_JCHG_MASK (511U << 0) -#define SDADC_JCHG(n) (1U << (n)) -/** @} */ - -/** - * @name SDADC channels definitions - * @{ - */ -#define SDADC_CHANNEL_0 SDADC_JCHG(0) -#define SDADC_CHANNEL_1 SDADC_JCHG(1) -#define SDADC_CHANNEL_2 SDADC_JCHG(2) -#define SDADC_CHANNEL_3 SDADC_JCHG(3) -#define SDADC_CHANNEL_4 SDADC_JCHG(4) -#define SDADC_CHANNEL_5 SDADC_JCHG(5) -#define SDADC_CHANNEL_6 SDADC_JCHG(6) -#define SDADC_CHANNEL_7 SDADC_JCHG(7) -#define SDADC_CHANNEL_8 SDADC_JCHG(8) -#define SDADC_CHANNEL_9 SDADC_JCHG(9) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief SDADC1 driver enable switch. - * @details If set to @p TRUE the support for SDADC1 is included. - */ -#if !defined(STM32_ADC_USE_SDADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_SDADC1 FALSE -#endif - -/** - * @brief SDADC2 driver enable switch. - * @details If set to @p TRUE the support for SDADC2 is included. - */ -#if !defined(STM32_ADC_USE_SDADC2) || defined(__DOXYGEN__) -#define STM32_ADC_USE_SDADC2 FALSE -#endif - -/** - * @brief SDADC3 driver enable switch. - * @details If set to @p TRUE the support for SDADC3 is included. - */ -#if !defined(STM32_ADC_USE_SDADC3) || defined(__DOXYGEN__) -#define STM32_ADC_USE_SDADC3 FALSE -#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 SDADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_SDADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief SDADC2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_SDADC2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC2_DMA_PRIORITY 2 -#endif - -/** - * @brief SDADC3 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_SDADC3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC3_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC 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 SDADC1 interrupt priority level setting. - */ -#if !defined(STM32_ADC_SDADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC1_IRQ_PRIORITY 5 -#endif - -/** - * @brief SDADC2 interrupt priority level setting. - */ -#if !defined(STM32_ADC_SDADC2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC2_IRQ_PRIORITY 5 -#endif - -/** - * @brief SDADC3 interrupt priority level setting. - */ -#if !defined(STM32_ADC_SDADC3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC3_IRQ_PRIORITY 5 -#endif - -/** - * @brief SDADC1 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_SDADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC1_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief SDADC2 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_SDADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC2_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief SDADC3 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_SDADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_SDADC3_DMA_IRQ_PRIORITY 5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** - * @brief At least an ADC unit is in use. - */ -#define STM32_ADC_USE_ADC STM32_ADC_USE_ADC1 - -/** - * @brief At least an SDADC unit is in use. - */ -#define STM32_ADC_USE_SDADC (STM32_ADC_USE_SDADC1 || \ - STM32_ADC_USE_SDADC2 || \ - STM32_ADC_USE_SDADC3) - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if STM32_ADC_USE_SDADC1 && !STM32_HAS_SDADC1 -#error "SDADC1 not present in the selected device" -#endif - -#if STM32_ADC_USE_SDADC2 && !STM32_HAS_SDADC2 -#error "SDADC2 not present in the selected device" -#endif - -#if STM32_ADC_USE_SDADC3 && !STM32_HAS_SDADC3 -#error "SDADC3 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC && !STM32_ADC_USE_SDADC -#error "ADC driver activated but no ADC/SDADC peripheral assigned" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_SDADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDADC1" -#endif - -#if STM32_ADC_USE_SDADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDADC1 DMA" -#endif - -#if STM32_ADC_USE_SDADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_SDADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDADC1" -#endif - -#if STM32_ADC_USE_SDADC2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDADC2" -#endif - -#if STM32_ADC_USE_SDADC2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC2_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDADC2 DMA" -#endif - -#if STM32_ADC_USE_SDADC2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_SDADC2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDADC2" -#endif - -#if STM32_ADC_USE_SDADC3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDADC3" -#endif - -#if STM32_ADC_USE_SDADC3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC3_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDADC3 DMA" -#endif - -#if STM32_ADC_USE_SDADC3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_SDADC3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDADC3" -#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. */ - ADC_ERR_AWD1 = 2 /**< Watchdog 1 triggered. */ -} adcerror_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -#if (STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC) || defined(__DOXYGEN__) -/** - * @brief Low level fields of the ADC driver structure. - */ -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to the SDADCx registers block.*/ \ - SDADC_TypeDef *sdadc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* SDADC CR1 register initialization data.*/ \ - uint32_t cr1; \ - /* SDADC CONFxR registers initialization data.*/ \ - uint32_t confxr[3] - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_configuration_group_fields \ - union { \ - struct { \ - /* 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; \ - /* 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; \ - /* ADC LTR register initialization data.*/ \ - uint32_t ltr; \ - /* ADC HTR register initialization data.*/ \ - uint32_t htr; \ - /* ADC SMPRx registers initialization data.*/ \ - uint32_t smpr[2]; \ - /* ADC SQRx register initialization data.*/ \ - uint32_t sqr[3]; \ - } adc; \ - struct { \ - /* SDADC CR2 register initialization data. \ - NOTE: Only the @p SDADC_CR2_JSWSTART, @p SDADC_CR2_JEXTSEL \ - and @p SDADC_CR2_JEXTEN can be specified in this field.*/ \ - uint32_t cr2; \ - /* SDADC JCHGR register initialization data.*/ \ - uint32_t jchgr; \ - /* SDADC CONFCHxR registers initialization data.*/ \ - uint32_t confchr[2]; \ - } sdadc; \ - } u - -#elif STM32_ADC_USE_ADC -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -#define adc_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -#define adc_lld_configuration_group_fields \ - union { \ - struct { \ - /* 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; \ - /* 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; \ - /* ADC LTR register initialization data.*/ \ - uint32_t ltr; \ - /* ADC HTR register initialization data.*/ \ - uint32_t htr; \ - /* ADC SMPRx registers initialization data.*/ \ - uint32_t smpr[2]; \ - /* ADC SQRx register initialization data.*/ \ - uint32_t sqr[3]; \ - } adc; \ - } u - -#elif STM32_ADC_USE_SDADC -#define adc_lld_driver_fields \ - /* Pointer to the SDADCx registers block.*/ \ - SDADC_TypeDef *sdadc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -#define adc_lld_config_fields \ - /* SDADC CR1 register initialization data.*/ \ - uint32_t cr1; \ - /* SDADC CONFxR registers initialization data.*/ \ - uint32_t confxr[3] - -#define adc_lld_configuration_group_fields \ - union { \ - struct { \ - /* SDADC CR2 register initialization data. \ - NOTE: Only the @p SDADC_CR2_JSWSTART, @p SDADC_CR2_JEXTSEL \ - and @p SDADC_CR2_JEXTEN can be specified in this field.*/ \ - uint32_t cr2; \ - /* SDADC JCHGR register initialization data.*/ \ - uint32_t jchgr; \ - /* SDADC CONFCHxR registers initialization data.*/ \ - uint32_t confchr[2]; \ - } sdadc; \ - } u - -#endif - -/** - * @name Sequences building helper macros for ADC - * @{ - */ -/** - * @brief Number of channels in a conversion sequence. - */ -#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) -#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.*/ - -#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_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. */ -/** @} */ - -/** - * @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. */ -/** @} */ - -/** - * @name Sequences building helper macros for SDADC - * @{ - */ -#define SDADC_JCHGR_CH(n) (1U << (n)) -/** @} */ - -/** - * @name Channel configuration number helper macros for SDADC - * @{ - */ -#define SDADC_CONFCHR1_CH0(n) ((n) << 0) -#define SDADC_CONFCHR1_CH1(n) ((n) << 4) -#define SDADC_CONFCHR1_CH2(n) ((n) << 8) -#define SDADC_CONFCHR1_CH3(n) ((n) << 12) -#define SDADC_CONFCHR1_CH4(n) ((n) << 16) -#define SDADC_CONFCHR1_CH5(n) ((n) << 20) -#define SDADC_CONFCHR1_CH6(n) ((n) << 24) -#define SDADC_CONFCHR1_CH7(n) ((n) << 28) -#define SDADC_CONFCHR2_CH8(n) ((n) << 0) -/** @} */ - -/** - * @name Configuration registers helper macros for SDADC - * @{ - */ -#define SDADC_CONFR_OFFSET_MASK (0xFFFU << 0) -#define SDADC_CONFR_OFFSET(n) ((n) << 0) -#define SDADC_CONFR_GAIN_MASK (7U << 20) -#define SDADC_CONFR_GAIN_1X (0U << 20) -#define SDADC_CONFR_GAIN_2X (1U << 20) -#define SDADC_CONFR_GAIN_4X (2U << 20) -#define SDADC_CONFR_GAIN_8X (3U << 20) -#define SDADC_CONFR_GAIN_16X (4U << 20) -#define SDADC_CONFR_GAIN_32X (5U << 20) -#define SDADC_CONFR_GAIN_0P5X (7U << 20) -#define SDADC_CONFR_SE_MASK (3U << 26) -#define SDADC_CONFR_SE_DIFF (0U << 26) -#define SDADC_CONFR_SE_OFFSET (1U << 26) -#define SDADC_CONFR_SE_ZERO_VOLT (3U << 26) -#define SDADC_CONFR_COMMON_MASK (3U << 30) -#define SDADC_CONFR_COMMON_VSSSD (0U << 30) -#define SDADC_CONFR_COMMON_VDDSD2 (1U << 30) -#define SDADC_CONFR_COMMON_VDDSD (2U << 30) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#if STM32_ADC_USE_SDADC1 && !defined(__DOXYGEN__) -extern ADCDriver SDADCD1; -#endif - -#if STM32_ADC_USE_SDADC2 && !defined(__DOXYGEN__) -extern ADCDriver SDADCD2; -#endif - -#if STM32_ADC_USE_SDADC3 && !defined(__DOXYGEN__) -extern ADCDriver SDADCD3; -#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 adcSTM32Calibrate(ADCDriver *adcdp); -#if STM32_ADC_USE_ADC - void adcSTM32EnableTSVREFE(void); - void adcSTM32DisableTSVREFE(void); - void adcSTM32EnableVBATE(void); - void adcSTM32DisableVBATE(void); -#endif /* STM32_ADC_USE_ADC */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/hal_adc_lld.h + * @brief STM32F37x ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Triggers selection + * @{ + */ +#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @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.*/ +#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ +#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */ +#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */ +#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */ +#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */ +#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */ +#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */ +#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */ +#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */ +/** @} */ + +/** + * @name SDADC JCHGR bit definitions + * @{ + */ +#define SDADC_JCHG_MASK (511U << 0) +#define SDADC_JCHG(n) (1U << (n)) +/** @} */ + +/** + * @name SDADC channels definitions + * @{ + */ +#define SDADC_CHANNEL_0 SDADC_JCHG(0) +#define SDADC_CHANNEL_1 SDADC_JCHG(1) +#define SDADC_CHANNEL_2 SDADC_JCHG(2) +#define SDADC_CHANNEL_3 SDADC_JCHG(3) +#define SDADC_CHANNEL_4 SDADC_JCHG(4) +#define SDADC_CHANNEL_5 SDADC_JCHG(5) +#define SDADC_CHANNEL_6 SDADC_JCHG(6) +#define SDADC_CHANNEL_7 SDADC_JCHG(7) +#define SDADC_CHANNEL_8 SDADC_JCHG(8) +#define SDADC_CHANNEL_9 SDADC_JCHG(9) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief SDADC1 driver enable switch. + * @details If set to @p TRUE the support for SDADC1 is included. + */ +#if !defined(STM32_ADC_USE_SDADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_SDADC1 FALSE +#endif + +/** + * @brief SDADC2 driver enable switch. + * @details If set to @p TRUE the support for SDADC2 is included. + */ +#if !defined(STM32_ADC_USE_SDADC2) || defined(__DOXYGEN__) +#define STM32_ADC_USE_SDADC2 FALSE +#endif + +/** + * @brief SDADC3 driver enable switch. + * @details If set to @p TRUE the support for SDADC3 is included. + */ +#if !defined(STM32_ADC_USE_SDADC3) || defined(__DOXYGEN__) +#define STM32_ADC_USE_SDADC3 FALSE +#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 SDADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_SDADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief SDADC2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_SDADC2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC2_DMA_PRIORITY 2 +#endif + +/** + * @brief SDADC3 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_SDADC3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC3_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC 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 SDADC1 interrupt priority level setting. + */ +#if !defined(STM32_ADC_SDADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC1_IRQ_PRIORITY 5 +#endif + +/** + * @brief SDADC2 interrupt priority level setting. + */ +#if !defined(STM32_ADC_SDADC2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC2_IRQ_PRIORITY 5 +#endif + +/** + * @brief SDADC3 interrupt priority level setting. + */ +#if !defined(STM32_ADC_SDADC3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC3_IRQ_PRIORITY 5 +#endif + +/** + * @brief SDADC1 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_SDADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC1_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief SDADC2 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_SDADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC2_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief SDADC3 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_SDADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_SDADC3_DMA_IRQ_PRIORITY 5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @brief At least an ADC unit is in use. + */ +#define STM32_ADC_USE_ADC STM32_ADC_USE_ADC1 + +/** + * @brief At least an SDADC unit is in use. + */ +#define STM32_ADC_USE_SDADC (STM32_ADC_USE_SDADC1 || \ + STM32_ADC_USE_SDADC2 || \ + STM32_ADC_USE_SDADC3) + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if STM32_ADC_USE_SDADC1 && !STM32_HAS_SDADC1 +#error "SDADC1 not present in the selected device" +#endif + +#if STM32_ADC_USE_SDADC2 && !STM32_HAS_SDADC2 +#error "SDADC2 not present in the selected device" +#endif + +#if STM32_ADC_USE_SDADC3 && !STM32_HAS_SDADC3 +#error "SDADC3 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC && !STM32_ADC_USE_SDADC +#error "ADC driver activated but no ADC/SDADC peripheral assigned" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_SDADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDADC1" +#endif + +#if STM32_ADC_USE_SDADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDADC1 DMA" +#endif + +#if STM32_ADC_USE_SDADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_SDADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDADC1" +#endif + +#if STM32_ADC_USE_SDADC2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDADC2" +#endif + +#if STM32_ADC_USE_SDADC2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC2_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDADC2 DMA" +#endif + +#if STM32_ADC_USE_SDADC2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_SDADC2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDADC2" +#endif + +#if STM32_ADC_USE_SDADC3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDADC3" +#endif + +#if STM32_ADC_USE_SDADC3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_SDADC3_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDADC3 DMA" +#endif + +#if STM32_ADC_USE_SDADC3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_SDADC3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDADC3" +#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. */ + ADC_ERR_AWD1 = 2 /**< Watchdog 1 triggered. */ +} adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#if (STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC) || defined(__DOXYGEN__) +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to the SDADCx registers block.*/ \ + SDADC_TypeDef *sdadc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* SDADC CR1 register initialization data.*/ \ + uint32_t cr1; \ + /* SDADC CONFxR registers initialization data.*/ \ + uint32_t confxr[3] + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_configuration_group_fields \ + union { \ + struct { \ + /* 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; \ + /* 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; \ + /* ADC LTR register initialization data.*/ \ + uint32_t ltr; \ + /* ADC HTR register initialization data.*/ \ + uint32_t htr; \ + /* ADC SMPRx registers initialization data.*/ \ + uint32_t smpr[2]; \ + /* ADC SQRx register initialization data.*/ \ + uint32_t sqr[3]; \ + } adc; \ + struct { \ + /* SDADC CR2 register initialization data. \ + NOTE: Only the @p SDADC_CR2_JSWSTART, @p SDADC_CR2_JEXTSEL \ + and @p SDADC_CR2_JEXTEN can be specified in this field.*/ \ + uint32_t cr2; \ + /* SDADC JCHGR register initialization data.*/ \ + uint32_t jchgr; \ + /* SDADC CONFCHxR registers initialization data.*/ \ + uint32_t confchr[2]; \ + } sdadc; \ + } u + +#elif STM32_ADC_USE_ADC +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +#define adc_lld_configuration_group_fields \ + union { \ + struct { \ + /* 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; \ + /* 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; \ + /* ADC LTR register initialization data.*/ \ + uint32_t ltr; \ + /* ADC HTR register initialization data.*/ \ + uint32_t htr; \ + /* ADC SMPRx registers initialization data.*/ \ + uint32_t smpr[2]; \ + /* ADC SQRx register initialization data.*/ \ + uint32_t sqr[3]; \ + } adc; \ + } u + +#elif STM32_ADC_USE_SDADC +#define adc_lld_driver_fields \ + /* Pointer to the SDADCx registers block.*/ \ + SDADC_TypeDef *sdadc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +#define adc_lld_config_fields \ + /* SDADC CR1 register initialization data.*/ \ + uint32_t cr1; \ + /* SDADC CONFxR registers initialization data.*/ \ + uint32_t confxr[3] + +#define adc_lld_configuration_group_fields \ + union { \ + struct { \ + /* SDADC CR2 register initialization data. \ + NOTE: Only the @p SDADC_CR2_JSWSTART, @p SDADC_CR2_JEXTSEL \ + and @p SDADC_CR2_JEXTEN can be specified in this field.*/ \ + uint32_t cr2; \ + /* SDADC JCHGR register initialization data.*/ \ + uint32_t jchgr; \ + /* SDADC CONFCHxR registers initialization data.*/ \ + uint32_t confchr[2]; \ + } sdadc; \ + } u + +#endif + +/** + * @name Sequences building helper macros for ADC + * @{ + */ +/** + * @brief Number of channels in a conversion sequence. + */ +#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) +#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.*/ + +#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_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. */ +/** @} */ + +/** + * @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. */ +/** @} */ + +/** + * @name Sequences building helper macros for SDADC + * @{ + */ +#define SDADC_JCHGR_CH(n) (1U << (n)) +/** @} */ + +/** + * @name Channel configuration number helper macros for SDADC + * @{ + */ +#define SDADC_CONFCHR1_CH0(n) ((n) << 0) +#define SDADC_CONFCHR1_CH1(n) ((n) << 4) +#define SDADC_CONFCHR1_CH2(n) ((n) << 8) +#define SDADC_CONFCHR1_CH3(n) ((n) << 12) +#define SDADC_CONFCHR1_CH4(n) ((n) << 16) +#define SDADC_CONFCHR1_CH5(n) ((n) << 20) +#define SDADC_CONFCHR1_CH6(n) ((n) << 24) +#define SDADC_CONFCHR1_CH7(n) ((n) << 28) +#define SDADC_CONFCHR2_CH8(n) ((n) << 0) +/** @} */ + +/** + * @name Configuration registers helper macros for SDADC + * @{ + */ +#define SDADC_CONFR_OFFSET_MASK (0xFFFU << 0) +#define SDADC_CONFR_OFFSET(n) ((n) << 0) +#define SDADC_CONFR_GAIN_MASK (7U << 20) +#define SDADC_CONFR_GAIN_1X (0U << 20) +#define SDADC_CONFR_GAIN_2X (1U << 20) +#define SDADC_CONFR_GAIN_4X (2U << 20) +#define SDADC_CONFR_GAIN_8X (3U << 20) +#define SDADC_CONFR_GAIN_16X (4U << 20) +#define SDADC_CONFR_GAIN_32X (5U << 20) +#define SDADC_CONFR_GAIN_0P5X (7U << 20) +#define SDADC_CONFR_SE_MASK (3U << 26) +#define SDADC_CONFR_SE_DIFF (0U << 26) +#define SDADC_CONFR_SE_OFFSET (1U << 26) +#define SDADC_CONFR_SE_ZERO_VOLT (3U << 26) +#define SDADC_CONFR_COMMON_MASK (3U << 30) +#define SDADC_CONFR_COMMON_VSSSD (0U << 30) +#define SDADC_CONFR_COMMON_VDDSD2 (1U << 30) +#define SDADC_CONFR_COMMON_VDDSD (2U << 30) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#if STM32_ADC_USE_SDADC1 && !defined(__DOXYGEN__) +extern ADCDriver SDADCD1; +#endif + +#if STM32_ADC_USE_SDADC2 && !defined(__DOXYGEN__) +extern ADCDriver SDADCD2; +#endif + +#if STM32_ADC_USE_SDADC3 && !defined(__DOXYGEN__) +extern ADCDriver SDADCD3; +#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 adcSTM32Calibrate(ADCDriver *adcdp); +#if STM32_ADC_USE_ADC + void adcSTM32EnableTSVREFE(void); + void adcSTM32DisableTSVREFE(void); + void adcSTM32EnableVBATE(void); + void adcSTM32DisableVBATE(void); +#endif /* STM32_ADC_USE_ADC */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/hal_lld.c b/os/hal/ports/STM32/STM32F37x/hal_lld.c index 902f688ac4..42620437ca 100644 --- a/os/hal/ports/STM32/STM32F37x/hal_lld.c +++ b/os/hal/ports/STM32/STM32F37x/hal_lld.c @@ -1,223 +1,224 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/hal_lld.c - * @brief STM32F37x HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f3xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB(~STM32_GPIO_EN_MASK); - rccResetAPB1(0xFFFFFFFF); - rccResetAPB2(0xFFFFFFFF); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -} - -/** - * @brief STM32 clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. Clearing the register has to be postponed after HSI is the - new source.*/ - RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers finally cleared to reset values.*/ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - - /* Clock settings.*/ - RCC->CFGR = STM32_SDPRE | STM32_MCOSEL | STM32_USBPRE | - STM32_PLLMUL | STM32_PLLSRC | STM32_ADCPRE | - STM32_PPRE1 | STM32_PPRE2 | STM32_HPRE; - RCC->CFGR2 = STM32_PREDIV; - RCC->CFGR3 = STM32_USART3SW | STM32_USART2SW | STM32_I2C2SW | - STM32_I2C1SW | STM32_USART1SW; - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - /* Switches clock source.*/ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; /* Waits selection complete. */ -#endif -#endif /* !STM32_NO_INIT */ -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/hal_lld.c + * @brief STM32F37x HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f3xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB(~STM32_GPIO_EN_MASK); + rccResetAPB1(0xFFFFFFFF); + rccResetAPB2(0xFFFFFFFF); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** + * @brief STM32 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. Clearing the register has to be postponed after HSI is the + new source.*/ + RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers finally cleared to reset values.*/ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + + /* Clock settings.*/ + RCC->CFGR = STM32_SDPRE | STM32_MCOSEL | STM32_USBPRE | + STM32_PLLMUL | STM32_PLLSRC | STM32_ADCPRE | + STM32_PPRE1 | STM32_PPRE2 | STM32_HPRE; + RCC->CFGR2 = STM32_PREDIV; + RCC->CFGR3 = STM32_USART3SW | STM32_USART2SW | STM32_I2C2SW | + STM32_I2C1SW | STM32_USART1SW; + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + /* Switches clock source.*/ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; /* Waits selection complete. */ +#endif +#endif /* !STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/hal_lld.h b/os/hal/ports/STM32/STM32F37x/hal_lld.h index 4214a56b5c..0556b28022 100644 --- a/os/hal/ports/STM32/STM32F37x/hal_lld.h +++ b/os/hal/ports/STM32/STM32F37x/hal_lld.h @@ -1,1030 +1,1038 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/hal_lld.h - * @brief STM32F37x 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32F373xC for Analog & DSP devices. - * - STM32F378xx for Analog & DSP devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32F373xC) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F373xC Analog & DSP" - -#elif defined(STM32F378xx) -#define PLATFORM_NAME "STM32F378xx Analog & DSP" - -#else -#error "STM32F7x device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32F37X) || defined(__DOXYGEN__) -#define STM32F37X -#endif -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 72000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @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 24000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 72000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 36000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 72000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 14000000 - -/** - * @brief Minimum ADC clock frequency. - */ -#define STM32_ADCCLK_MIN 600000 - -/** - * @brief Maximum SDADC clock frequency in fast mode. - */ -#define STM32_SDADCCLK_FAST_MAX 6000000 - -/** - * @brief Maximum SDADC clock frequency in slow mode. - */ -#define STM32_SDADCCLK_SLOW_MAX 1500000 - -/** - * @brief Minimum SDADC clock frequency. - */ -#define STM32_SDADCCLK_MIN 500000 -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 8000000 /**< High speed internal clock. */ -#define STM32_LSICLK 40000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7U << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0U << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1U << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2U << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3U << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4U << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5U << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6U << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7U << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0U << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1U << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2U << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0U << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8u << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9U << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10U << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11U << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12U << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13U << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14U << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15U << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0U << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4U << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5U << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6U << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7U << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0U << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4U << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5U << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6U << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7U << 11) /**< HCLK divided by 16. */ - -#define STM32_ADCPRE_DIV2 (0U << 14) /**< PPRE2 divided by 2. */ -#define STM32_ADCPRE_DIV4 (1U << 14) /**< PPRE2 divided by 4. */ -#define STM32_ADCPRE_DIV6 (2U << 14) /**< PPRE2 divided by 6. */ -#define STM32_ADCPRE_DIV8 (3U << 14) /**< PPRE2 divided by 8. */ - -#define STM32_PLLSRC_HSI (0U << 16) /**< PLL clock source is HSI/2. */ -#define STM32_PLLSRC_HSE (1U << 16) /**< PLL clock source is - HSE/PREDIV. */ - -#define STM32_USBPRE_DIV1P5 (0U << 22) /**< USB clock is PLLCLK/1.5. */ -#define STM32_USBPRE_DIV1 (1U << 22) /**< USB clock is PLLCLK/1. */ - -#define STM32_MCOSEL_NOCLOCK (0U << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_LSI (2U << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (3U << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4U << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5U << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6U << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7U << 24) /**< PLL/2 clock on MCO pin. */ - -#define STM32_SDPRE_DIV2 (16U << 27) /**< SYSCLK divided by 2. */ -#define STM32_SDPRE_DIV4 (17U << 27) /**< SYSCLK divided by 4. */ -#define STM32_SDPRE_DIV6 (18U << 27) /**< SYSCLK divided by 6. */ -#define STM32_SDPRE_DIV8 (19U << 27) /**< SYSCLK divided by 8. */ -#define STM32_SDPRE_DIV10 (20U << 27) /**< SYSCLK divided by 10. */ -#define STM32_SDPRE_DIV12 (21U << 27) /**< SYSCLK divided by 12. */ -#define STM32_SDPRE_DIV14 (22U << 27) /**< SYSCLK divided by 14. */ -#define STM32_SDPRE_DIV16 (23U << 27) /**< SYSCLK divided by 16. */ -#define STM32_SDPRE_DIV20 (24U << 27) /**< SYSCLK divided by 20. */ -#define STM32_SDPRE_DIV24 (25U << 27) /**< SYSCLK divided by 24. */ -#define STM32_SDPRE_DIV28 (26U << 27) /**< SYSCLK divided by 28. */ -#define STM32_SDPRE_DIV32 (27U << 27) /**< SYSCLK divided by 32. */ -#define STM32_SDPRE_DIV36 (28U << 27) /**< SYSCLK divided by 36. */ -#define STM32_SDPRE_DIV40 (29U << 27) /**< SYSCLK divided by 40. */ -#define STM32_SDPRE_DIV44 (30U << 27) /**< SYSCLK divided by 44. */ -#define STM32_SDPRE_DIV48 (31U << 27) /**< SYSCLK divided by 48. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3U << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0U << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1U << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2U << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3U << 8) /**< HSE divided by 32 used as - RTC clock. */ -/** @} */ - -/** - * @name RCC_CFGR2 register bits definitions - * @{ - */ -#define STM32_PREDIV_MASK (15U << 0) /**< PREDIV divisor mask. */ -/** @} */ - -/** - * @name RCC_CFGR3 register bits definitions - * @{ - */ -#define STM32_USART1SW_MASK (3U << 0) /**< USART1 clock source mask. */ -#define STM32_USART1SW_PCLK (0U << 0) /**< USART1 clock is PCLK. */ -#define STM32_USART1SW_SYSCLK (1U << 0) /**< USART1 clock is SYSCLK. */ -#define STM32_USART1SW_LSE (2U << 0) /**< USART1 clock is LSE. */ -#define STM32_USART1SW_HSI (3U << 0) /**< USART1 clock is HSI. */ -#define STM32_I2C1SW_MASK (1U << 4) /**< I2C1 clock source mask. */ -#define STM32_I2C1SW_HSI (0U << 4) /**< I2C1 clock is HSI. */ -#define STM32_I2C1SW_SYSCLK (1U << 4) /**< I2C1 clock is SYSCLK. */ -#define STM32_I2C2SW_MASK (1U << 5) /**< I2C2 clock source mask. */ -#define STM32_I2C2SW_HSI (0U << 5) /**< I2C2 clock is HSI. */ -#define STM32_I2C2SW_SYSCLK (1U << 5) /**< I2C2 clock is SYSCLK. */ -#define STM32_USART2SW_MASK (3U << 16) /**< USART2 clock source mask. */ -#define STM32_USART2SW_PCLK (0U << 16) /**< USART2 clock is PCLK. */ -#define STM32_USART2SW_SYSCLK (1U << 16) /**< USART2 clock is SYSCLK. */ -#define STM32_USART2SW_LSE (2U << 16) /**< USART2 clock is LSE. */ -#define STM32_USART2SW_HSI (3U << 16) /**< USART2 clock is HSI. */ -#define STM32_USART3SW_MASK (3U << 18) /**< USART3 clock source mask. */ -#define STM32_USART3SW_PCLK (0U << 18) /**< USART3 clock is PCLK. */ -#define STM32_USART3SW_SYSCLK (1U << 18) /**< USART3 clock is SYSCLK. */ -#define STM32_USART3SW_LSE (2U << 18) /**< USART3 clock is LSE. */ -#define STM32_USART3SW_HSI (3U << 18) /**< USART3 clock is HSI. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV_VALUE 1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 9 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief ADC prescaler value. - */ -#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#endif - -/** - * @brief SDADC prescaler value. - */ -#if !defined(STM32_SDPRE) || defined(__DOXYGEN__) -#define STM32_SDPRE STM32_SDPRE_DIV12 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) -#define STM32_USART1SW STM32_USART1SW_PCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SW) || defined(__DOXYGEN__) -#define STM32_USART2SW STM32_USART2SW_PCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SW) || defined(__DOXYGEN__) -#define STM32_USART3SW STM32_USART3SW_PCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) -#define STM32_I2C1SW STM32_I2C1SW_SYSCLK -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SW) || defined(__DOXYGEN__) -#define STM32_I2C2SW STM32_I2C2SW_SYSCLK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif - -/** - * @brief USB clock setting. - */ -#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) -#define STM32_USB_CLOCK_REQUIRED TRUE -#endif - -/** - * @brief USB prescaler initialization. - */ -#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) -#define STM32_USBPRE STM32_USBPRE_DIV1P5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F37x_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F37x_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_HSI -#error "HSI not enabled, required by STM32_USART1SW" -#endif - -#if STM32_USART2SW == STM32_USART2SW_HSI -#error "HSI not enabled, required by STM32_USART2SW" -#endif - -#if STM32_USART3SW == STM32_USART3SW_HSI -#error "HSI not enabled, required by STM32_USART3SW" -#endif - -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#error "HSI not enabled, required by STM32_I2C1SW" -#endif - -#if STM32_I2C2SW == STM32_I2C2SW_HSI -#error "HSI not enabled, required by STM32_I2C2SW" -#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_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if !defined(STM32_LSECLK) || (STM32_LSECLK == 0) -#error "STM32_LSECLK 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 !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" -#endif - -#if STM32_USART1SW == STM32_USART1SW_LSE -#error "LSE not enabled, required by STM32_USART1SW" -#endif - -#if STM32_USART2SW == STM32_USART2SW_LSE -#error "LSE not enabled, required by STM32_USART2SW" -#endif - -#if STM32_USART3SW == STM32_USART3SW_LSE -#error "LSE not enabled, required by STM32_USART3SW" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - STM32_USB_CLOCK_REQUIRED || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE prescaler setting check.*/ -#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) -#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) -#else -#error "invalid STM32_PREDIV value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL 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 - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC 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) -#else -#error "invalid STM32_ADCPRE value specified" -#endif - -/* ADC maximum frequency check.*/ -#if STM32_ADC_USE_ADC1 && (STM32_ADCCLK > STM32_ADCCLK_MAX) -#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/* ADC minimum frequency check.*/ -#if STM32_ADC_USE_ADC1 && (STM32_ADCCLK < STM32_ADCCLK_MIN) -#error "STM32_ADCCLK exceeding minimum frequency (STM32_ADCCLK_MIN)" -#endif - -/** - * @brief SDADC frequency. - */ -#if (STM32_SDPRE == STM32_SDPRE_DIV2) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 2) -#elif (STM32_SDPRE == STM32_SDPRE_DIV4) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 4) -#elif (STM32_SDPRE == STM32_SDPRE_DIV6) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 6) -#elif (STM32_SDPRE == STM32_SDPRE_DIV8) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 8) -#elif (STM32_SDPRE == STM32_SDPRE_DIV10) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 10) -#elif (STM32_SDPRE == STM32_SDPRE_DIV12) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 12) -#elif (STM32_SDPRE == STM32_SDPRE_DIV14) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 14) -#elif (STM32_SDPRE == STM32_SDPRE_DIV16) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 16) -#elif (STM32_SDPRE == STM32_SDPRE_DIV20) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 20) -#elif (STM32_SDPRE == STM32_SDPRE_DIV24) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 24) -#elif (STM32_SDPRE == STM32_SDPRE_DIV28) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 28) -#elif (STM32_SDPRE == STM32_SDPRE_DIV32) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 32) -#elif (STM32_SDPRE == STM32_SDPRE_DIV36) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 36) -#elif (STM32_SDPRE == STM32_SDPRE_DIV40) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 40) -#elif (STM32_SDPRE == STM32_SDPRE_DIV44) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 44) -#elif (STM32_SDPRE == STM32_SDPRE_DIV48) || defined(__DOXYGEN__) -#define STM32_SDADCCLK (STM32_SYSCLK / 48) -#else -#error "invalid STM32_SDPRE value specified" -#endif - -/* SDADC maximum frequency check.*/ -#if (STM32_ADC_USE_SDADC1 || \ - STM32_ADC_USE_SDADC2 || \ - STM32_ADC_USE_SDADC3) && (STM32_SDADCCLK > STM32_SDADCCLK_FAST_MAX) -#error "STM32_SDADCCLK exceeding maximum frequency (STM32_SDADCCLK_FAST_MAX)" -#endif - -/* SDADC minimum frequency check.*/ -#if (STM32_ADC_USE_SDADC1 || \ - STM32_ADC_USE_SDADC2 || \ - STM32_ADC_USE_SDADC3) && \ - (STM32_SDADCCLK < STM32_SDADCCLK_MIN) -#error "STM32_SDADCCLK exceeding maximum frequency (STM32_SDADCCLK_MIN)" -#endif - -/** - * @brief I2C1 frequency. - */ -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#define STM32_I2C1CLK STM32_HSICLK -#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 frequency. - */ -#if STM32_I2C2SW == STM32_I2C2SW_HSI -#define STM32_I2C2CLK STM32_HSICLK -#elif STM32_I2C2SW == STM32_I2C2SW_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief USART1 frequency. - */ -#if STM32_USART1SW == STM32_USART1SW_PCLK -#define STM32_USART1CLK STM32_PCLK2 -#elif STM32_USART1SW == STM32_USART1SW_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SW == STM32_USART1SW_LSE -#define STM32_USART1CLK STM32_LSECLK -#elif STM32_USART1SW == STM32_USART1SW_HSI -#define STM32_USART1CLK STM32_HSICLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#if STM32_USART2SW == STM32_USART2SW_PCLK -#define STM32_USART2CLK STM32_PCLK1 -#elif STM32_USART2SW == STM32_USART2SW_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SW == STM32_USART2SW_LSE -#define STM32_USART2CLK STM32_LSECLK -#elif STM32_USART2SW == STM32_USART2SW_HSI -#define STM32_USART2CLK STM32_HSICLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 frequency. - */ -#if STM32_USART3SW == STM32_USART3SW_PCLK -#define STM32_USART3CLK STM32_PCLK1 -#elif STM32_USART3SW == STM32_USART3SW_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK -#elif STM32_USART3SW == STM32_USART3SW_LSE -#define STM32_USART3CLK STM32_LSECLK -#elif STM32_USART3SW == STM32_USART3SW_HSI -#define STM32_USART3CLK STM32_HSICLK -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief Timers 2, 3, 4, 5, 6, 7, 12, 13, 14, 18 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 15, 16, 17, 19 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief USB frequency. - */ -#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) -#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) -#elif (STM32_USBPRE == STM32_USBPRE_DIV1) -#define STM32_USBCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_USBPRE value specified" -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#elif STM32_HCLK <= 48000000 -#define STM32_FLASHBITS 0x00000011 -#else -#define STM32_FLASHBITS 0x00000012 -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_registry.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/hal_lld.h + * @brief STM32F37x 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32F373xC for Analog & DSP devices. + * - STM32F378xx for Analog & DSP devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32F373xC) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F373xC Analog & DSP" + +#elif defined(STM32F378xx) +#define PLATFORM_NAME "STM32F378xx Analog & DSP" + +#else +#error "STM32F7x device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32F37X) || defined(__DOXYGEN__) +#define STM32F37X +#endif +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 72000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @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 24000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 72000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 36000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 72000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 14000000 + +/** + * @brief Minimum ADC clock frequency. + */ +#define STM32_ADCCLK_MIN 600000 + +/** + * @brief Maximum SDADC clock frequency in fast mode. + */ +#define STM32_SDADCCLK_FAST_MAX 6000000 + +/** + * @brief Maximum SDADC clock frequency in slow mode. + */ +#define STM32_SDADCCLK_SLOW_MAX 1500000 + +/** + * @brief Minimum SDADC clock frequency. + */ +#define STM32_SDADCCLK_MIN 500000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 8000000 /**< High speed internal clock. */ +#define STM32_LSICLK 40000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7U << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0U << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1U << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2U << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3U << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4U << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5U << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6U << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7U << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0U << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1U << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2U << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0U << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8u << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9U << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10U << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11U << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12U << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13U << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14U << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15U << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0U << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4U << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5U << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6U << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7U << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0U << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4U << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5U << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6U << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7U << 11) /**< HCLK divided by 16. */ + +#define STM32_ADCPRE_DIV2 (0U << 14) /**< PPRE2 divided by 2. */ +#define STM32_ADCPRE_DIV4 (1U << 14) /**< PPRE2 divided by 4. */ +#define STM32_ADCPRE_DIV6 (2U << 14) /**< PPRE2 divided by 6. */ +#define STM32_ADCPRE_DIV8 (3U << 14) /**< PPRE2 divided by 8. */ + +#define STM32_PLLSRC_HSI (0U << 16) /**< PLL clock source is HSI/2. */ +#define STM32_PLLSRC_HSE (1U << 16) /**< PLL clock source is + HSE/PREDIV. */ + +#define STM32_USBPRE_DIV1P5 (0U << 22) /**< USB clock is PLLCLK/1.5. */ +#define STM32_USBPRE_DIV1 (1U << 22) /**< USB clock is PLLCLK/1. */ + +#define STM32_MCOSEL_NOCLOCK (0U << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_LSI (2U << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (3U << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4U << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5U << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6U << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7U << 24) /**< PLL/2 clock on MCO pin. */ + +#define STM32_SDPRE_DIV2 (16U << 27) /**< SYSCLK divided by 2. */ +#define STM32_SDPRE_DIV4 (17U << 27) /**< SYSCLK divided by 4. */ +#define STM32_SDPRE_DIV6 (18U << 27) /**< SYSCLK divided by 6. */ +#define STM32_SDPRE_DIV8 (19U << 27) /**< SYSCLK divided by 8. */ +#define STM32_SDPRE_DIV10 (20U << 27) /**< SYSCLK divided by 10. */ +#define STM32_SDPRE_DIV12 (21U << 27) /**< SYSCLK divided by 12. */ +#define STM32_SDPRE_DIV14 (22U << 27) /**< SYSCLK divided by 14. */ +#define STM32_SDPRE_DIV16 (23U << 27) /**< SYSCLK divided by 16. */ +#define STM32_SDPRE_DIV20 (24U << 27) /**< SYSCLK divided by 20. */ +#define STM32_SDPRE_DIV24 (25U << 27) /**< SYSCLK divided by 24. */ +#define STM32_SDPRE_DIV28 (26U << 27) /**< SYSCLK divided by 28. */ +#define STM32_SDPRE_DIV32 (27U << 27) /**< SYSCLK divided by 32. */ +#define STM32_SDPRE_DIV36 (28U << 27) /**< SYSCLK divided by 36. */ +#define STM32_SDPRE_DIV40 (29U << 27) /**< SYSCLK divided by 40. */ +#define STM32_SDPRE_DIV44 (30U << 27) /**< SYSCLK divided by 44. */ +#define STM32_SDPRE_DIV48 (31U << 27) /**< SYSCLK divided by 48. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3U << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0U << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1U << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2U << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3U << 8) /**< HSE divided by 32 used as + RTC clock. */ +/** @} */ + +/** + * @name RCC_CFGR2 register bits definitions + * @{ + */ +#define STM32_PREDIV_MASK (15U << 0) /**< PREDIV divisor mask. */ +/** @} */ + +/** + * @name RCC_CFGR3 register bits definitions + * @{ + */ +#define STM32_USART1SW_MASK (3U << 0) /**< USART1 clock source mask. */ +#define STM32_USART1SW_PCLK (0U << 0) /**< USART1 clock is PCLK. */ +#define STM32_USART1SW_SYSCLK (1U << 0) /**< USART1 clock is SYSCLK. */ +#define STM32_USART1SW_LSE (2U << 0) /**< USART1 clock is LSE. */ +#define STM32_USART1SW_HSI (3U << 0) /**< USART1 clock is HSI. */ +#define STM32_I2C1SW_MASK (1U << 4) /**< I2C1 clock source mask. */ +#define STM32_I2C1SW_HSI (0U << 4) /**< I2C1 clock is HSI. */ +#define STM32_I2C1SW_SYSCLK (1U << 4) /**< I2C1 clock is SYSCLK. */ +#define STM32_I2C2SW_MASK (1U << 5) /**< I2C2 clock source mask. */ +#define STM32_I2C2SW_HSI (0U << 5) /**< I2C2 clock is HSI. */ +#define STM32_I2C2SW_SYSCLK (1U << 5) /**< I2C2 clock is SYSCLK. */ +#define STM32_USART2SW_MASK (3U << 16) /**< USART2 clock source mask. */ +#define STM32_USART2SW_PCLK (0U << 16) /**< USART2 clock is PCLK. */ +#define STM32_USART2SW_SYSCLK (1U << 16) /**< USART2 clock is SYSCLK. */ +#define STM32_USART2SW_LSE (2U << 16) /**< USART2 clock is LSE. */ +#define STM32_USART2SW_HSI (3U << 16) /**< USART2 clock is HSI. */ +#define STM32_USART3SW_MASK (3U << 18) /**< USART3 clock source mask. */ +#define STM32_USART3SW_PCLK (0U << 18) /**< USART3 clock is PCLK. */ +#define STM32_USART3SW_SYSCLK (1U << 18) /**< USART3 clock is SYSCLK. */ +#define STM32_USART3SW_LSE (2U << 18) /**< USART3 clock is LSE. */ +#define STM32_USART3SW_HSI (3U << 18) /**< USART3 clock is HSI. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV_VALUE 1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 9 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief ADC prescaler value. + */ +#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#endif + +/** + * @brief SDADC prescaler value. + */ +#if !defined(STM32_SDPRE) || defined(__DOXYGEN__) +#define STM32_SDPRE STM32_SDPRE_DIV12 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) +#define STM32_USART1SW STM32_USART1SW_PCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SW) || defined(__DOXYGEN__) +#define STM32_USART2SW STM32_USART2SW_PCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SW) || defined(__DOXYGEN__) +#define STM32_USART3SW STM32_USART3SW_PCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SW) || defined(__DOXYGEN__) +#define STM32_I2C2SW STM32_I2C2SW_SYSCLK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif + +/** + * @brief USB clock setting. + */ +#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) +#define STM32_USB_CLOCK_REQUIRED TRUE +#endif + +/** + * @brief USB prescaler initialization. + */ +#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) +#define STM32_USBPRE STM32_USBPRE_DIV1P5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F37x_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F37x_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_HSI +#error "HSI not enabled, required by STM32_USART1SW" +#endif + +#if STM32_USART2SW == STM32_USART2SW_HSI +#error "HSI not enabled, required by STM32_USART2SW" +#endif + +#if STM32_USART3SW == STM32_USART3SW_HSI +#error "HSI not enabled, required by STM32_USART3SW" +#endif + +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#error "HSI not enabled, required by STM32_I2C1SW" +#endif + +#if STM32_I2C2SW == STM32_I2C2SW_HSI +#error "HSI not enabled, required by STM32_I2C2SW" +#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_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if !defined(STM32_LSECLK) || (STM32_LSECLK == 0) +#error "STM32_LSECLK 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 !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" +#endif + +#if STM32_USART1SW == STM32_USART1SW_LSE +#error "LSE not enabled, required by STM32_USART1SW" +#endif + +#if STM32_USART2SW == STM32_USART2SW_LSE +#error "LSE not enabled, required by STM32_USART2SW" +#endif + +#if STM32_USART3SW == STM32_USART3SW_LSE +#error "LSE not enabled, required by STM32_USART3SW" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + STM32_USB_CLOCK_REQUIRED || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE prescaler setting check.*/ +#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) +#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) +#else +#error "invalid STM32_PREDIV value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL 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 + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC 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) +#else +#error "invalid STM32_ADCPRE value specified" +#endif + +/* ADC maximum frequency check.*/ +#if STM32_ADC_USE_ADC1 && (STM32_ADCCLK > STM32_ADCCLK_MAX) +#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/* ADC minimum frequency check.*/ +#if STM32_ADC_USE_ADC1 && (STM32_ADCCLK < STM32_ADCCLK_MIN) +#error "STM32_ADCCLK exceeding minimum frequency (STM32_ADCCLK_MIN)" +#endif + +/** + * @brief SDADC frequency. + */ +#if (STM32_SDPRE == STM32_SDPRE_DIV2) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 2) +#elif (STM32_SDPRE == STM32_SDPRE_DIV4) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 4) +#elif (STM32_SDPRE == STM32_SDPRE_DIV6) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 6) +#elif (STM32_SDPRE == STM32_SDPRE_DIV8) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 8) +#elif (STM32_SDPRE == STM32_SDPRE_DIV10) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 10) +#elif (STM32_SDPRE == STM32_SDPRE_DIV12) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 12) +#elif (STM32_SDPRE == STM32_SDPRE_DIV14) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 14) +#elif (STM32_SDPRE == STM32_SDPRE_DIV16) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 16) +#elif (STM32_SDPRE == STM32_SDPRE_DIV20) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 20) +#elif (STM32_SDPRE == STM32_SDPRE_DIV24) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 24) +#elif (STM32_SDPRE == STM32_SDPRE_DIV28) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 28) +#elif (STM32_SDPRE == STM32_SDPRE_DIV32) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 32) +#elif (STM32_SDPRE == STM32_SDPRE_DIV36) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 36) +#elif (STM32_SDPRE == STM32_SDPRE_DIV40) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 40) +#elif (STM32_SDPRE == STM32_SDPRE_DIV44) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 44) +#elif (STM32_SDPRE == STM32_SDPRE_DIV48) || defined(__DOXYGEN__) +#define STM32_SDADCCLK (STM32_SYSCLK / 48) +#else +#error "invalid STM32_SDPRE value specified" +#endif + +/* SDADC maximum frequency check.*/ +#if (STM32_ADC_USE_SDADC1 || \ + STM32_ADC_USE_SDADC2 || \ + STM32_ADC_USE_SDADC3) && (STM32_SDADCCLK > STM32_SDADCCLK_FAST_MAX) +#error "STM32_SDADCCLK exceeding maximum frequency (STM32_SDADCCLK_FAST_MAX)" +#endif + +/* SDADC minimum frequency check.*/ +#if (STM32_ADC_USE_SDADC1 || \ + STM32_ADC_USE_SDADC2 || \ + STM32_ADC_USE_SDADC3) && \ + (STM32_SDADCCLK < STM32_SDADCCLK_MIN) +#error "STM32_SDADCCLK exceeding maximum frequency (STM32_SDADCCLK_MIN)" +#endif + +/** + * @brief I2C1 frequency. + */ +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#define STM32_I2C1CLK STM32_HSICLK +#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 frequency. + */ +#if STM32_I2C2SW == STM32_I2C2SW_HSI +#define STM32_I2C2CLK STM32_HSICLK +#elif STM32_I2C2SW == STM32_I2C2SW_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief USART1 frequency. + */ +#if STM32_USART1SW == STM32_USART1SW_PCLK +#define STM32_USART1CLK STM32_PCLK2 +#elif STM32_USART1SW == STM32_USART1SW_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SW == STM32_USART1SW_LSE +#define STM32_USART1CLK STM32_LSECLK +#elif STM32_USART1SW == STM32_USART1SW_HSI +#define STM32_USART1CLK STM32_HSICLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#if STM32_USART2SW == STM32_USART2SW_PCLK +#define STM32_USART2CLK STM32_PCLK1 +#elif STM32_USART2SW == STM32_USART2SW_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SW == STM32_USART2SW_LSE +#define STM32_USART2CLK STM32_LSECLK +#elif STM32_USART2SW == STM32_USART2SW_HSI +#define STM32_USART2CLK STM32_HSICLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 frequency. + */ +#if STM32_USART3SW == STM32_USART3SW_PCLK +#define STM32_USART3CLK STM32_PCLK1 +#elif STM32_USART3SW == STM32_USART3SW_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK +#elif STM32_USART3SW == STM32_USART3SW_LSE +#define STM32_USART3CLK STM32_LSECLK +#elif STM32_USART3SW == STM32_USART3SW_HSI +#define STM32_USART3CLK STM32_HSICLK +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief Timers 2, 3, 4, 5, 6, 7, 12, 13, 14, 18 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 15, 16, 17, 19 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief USB frequency. + */ +#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) +#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) +#elif (STM32_USBPRE == STM32_USBPRE_DIV1) +#define STM32_USBCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_USBPRE value specified" +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#elif STM32_HCLK <= 48000000 +#define STM32_FLASHBITS 0x00000011 +#else +#define STM32_FLASHBITS 0x00000012 +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_registry.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/platform.mk b/os/hal/ports/STM32/STM32F37x/platform.mk index f807d3dae4..ad020d7e37 100644 --- a/os/hal/ports/STM32/STM32F37x/platform.mk +++ b/os/hal/ports/STM32/STM32F37x/platform.mk @@ -1,47 +1,47 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F37x - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F37x + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32F37x/hal_adc_lld.c +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F37x/stm32_isr.c b/os/hal/ports/STM32/STM32F37x/stm32_isr.c index 64f15b7e59..3336d030b9 100644 --- a/os/hal/ports/STM32/STM32F37x/stm32_isr.c +++ b/os/hal/ports/STM32/STM32F37x/stm32_isr.c @@ -1,255 +1,255 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/stm32_isr.c - * @brief STM32F3xx ISR handler code. - * - * @addtogroup STM32F3xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_EXTI0_HANDLER) -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 0); - EXTI->PR = pr; - - exti_serve_irq(pr, 0); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI1_HANDLER) -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 1); - EXTI->PR = pr; - - exti_serve_irq(pr, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_HANDLER) -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 2); - EXTI->PR = pr; - - exti_serve_irq(pr, 2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI3_HANDLER) -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 3); - EXTI->PR = pr; - - exti_serve_irq(pr, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_HANDLER) -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 4); - EXTI->PR = pr; - - exti_serve_irq(pr, 4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | - (1U << 9)); - EXTI->PR = pr; - - exti_serve_irq(pr, 5); - exti_serve_irq(pr, 6); - exti_serve_irq(pr, 7); - exti_serve_irq(pr, 8); - exti_serve_irq(pr, 9); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | - (1U << 14) | (1U << 15)); - EXTI->PR = pr; - - exti_serve_irq(pr, 10); - exti_serve_irq(pr, 11); - exti_serve_irq(pr, 12); - exti_serve_irq(pr, 13); - exti_serve_irq(pr, 14); - exti_serve_irq(pr, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#endif /* HAL_USE_PAL */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - -#if HAL_USE_PAL - nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); - nvicEnableVector(EXTI2_TSC_IRQn, STM32_IRQ_EXTI2_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); -#endif -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - -#if HAL_USE_PAL - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_TSC_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); -#endif -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/stm32_isr.c + * @brief STM32F3xx ISR handler code. + * + * @addtogroup STM32F3xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_EXTI0_HANDLER) +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 0); + EXTI->PR = pr; + + exti_serve_irq(pr, 0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI1_HANDLER) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 1); + EXTI->PR = pr; + + exti_serve_irq(pr, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_HANDLER) +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 2); + EXTI->PR = pr; + + exti_serve_irq(pr, 2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI3_HANDLER) +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 3); + EXTI->PR = pr; + + exti_serve_irq(pr, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_HANDLER) +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 4); + EXTI->PR = pr; + + exti_serve_irq(pr, 4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | + (1U << 9)); + EXTI->PR = pr; + + exti_serve_irq(pr, 5); + exti_serve_irq(pr, 6); + exti_serve_irq(pr, 7); + exti_serve_irq(pr, 8); + exti_serve_irq(pr, 9); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | + (1U << 14) | (1U << 15)); + EXTI->PR = pr; + + exti_serve_irq(pr, 10); + exti_serve_irq(pr, 11); + exti_serve_irq(pr, 12); + exti_serve_irq(pr, 13); + exti_serve_irq(pr, 14); + exti_serve_irq(pr, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#endif /* HAL_USE_PAL */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + +#if HAL_USE_PAL + nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); + nvicEnableVector(EXTI2_TSC_IRQn, STM32_IRQ_EXTI2_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); +#endif +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +#if HAL_USE_PAL + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_TSC_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); +#endif +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/stm32_isr.h b/os/hal/ports/STM32/STM32F37x/stm32_isr.h index d649110d35..7690f7d973 100644 --- a/os/hal/ports/STM32/STM32F37x/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F37x/stm32_isr.h @@ -1,243 +1,243 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/stm32_isr.h - * @brief STM32F37x ISR handler header. - * - * @addtogroup STM32F37x_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 - -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 - -/* - * TIM units. - */ -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM12_HANDLER VectorEC -#define STM32_TIM13_HANDLER VectorF0 -#define STM32_TIM14_HANDLER VectorF4 -#define STM32_TIM15_HANDLER VectorA0 -#define STM32_TIM16_HANDLER VectorA4 -#define STM32_TIM17_HANDLER VectorA8 -#define STM32_TIM18_HANDLER VectorAC -#define STM32_TIM19_HANDLER Vector178 - -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM12_NUMBER 43 -#define STM32_TIM13_NUMBER 44 -#define STM32_TIM14_NUMBER 45 -#define STM32_TIM15_NUMBER 24 -#define STM32_TIM16_NUMBER 25 -#define STM32_TIM17_NUMBER 26 -#define STM32_TIM18_NUMBER 27 -#define STM32_TIM19_NUMBER 78 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 - -/* - * USB units. - */ -#define STM32_USB1_HP_HANDLER Vector168 -#define STM32_USB1_LP_HANDLER Vector16C - -#define STM32_USB1_HP_NUMBER 74 -#define STM32_USB1_LP_NUMBER 75 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI0_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI1_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI2_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI3_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI4_PRIORITY 6 -#endif - -/** - * @brief EXTI5..9 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#endif - -/** - * @brief EXTI10..15 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI16_PRIORITY 6 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI17_PRIORITY 6 -#endif - -/** - * @brief EXTI18 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI18_PRIORITY 6 -#endif - -/** - * @brief EXTI19 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI19_PRIORITY 6 -#endif - -/** - * @brief EXTI20 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI20_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI20_PRIORITY 6 -#endif - -/** - * @brief EXTI21..22 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI21_22_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI21_22_PRIORITY 6 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/stm32_isr.h + * @brief STM32F37x ISR handler header. + * + * @addtogroup STM32F37x_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 + +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 + +/* + * TIM units. + */ +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM12_HANDLER VectorEC +#define STM32_TIM13_HANDLER VectorF0 +#define STM32_TIM14_HANDLER VectorF4 +#define STM32_TIM15_HANDLER VectorA0 +#define STM32_TIM16_HANDLER VectorA4 +#define STM32_TIM17_HANDLER VectorA8 +#define STM32_TIM18_HANDLER VectorAC +#define STM32_TIM19_HANDLER Vector178 + +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM12_NUMBER 43 +#define STM32_TIM13_NUMBER 44 +#define STM32_TIM14_NUMBER 45 +#define STM32_TIM15_NUMBER 24 +#define STM32_TIM16_NUMBER 25 +#define STM32_TIM17_NUMBER 26 +#define STM32_TIM18_NUMBER 27 +#define STM32_TIM19_NUMBER 78 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 + +/* + * USB units. + */ +#define STM32_USB1_HP_HANDLER Vector168 +#define STM32_USB1_LP_HANDLER Vector16C + +#define STM32_USB1_HP_NUMBER 74 +#define STM32_USB1_LP_NUMBER 75 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI0_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI1_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI2_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI3_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI4_PRIORITY 6 +#endif + +/** + * @brief EXTI5..9 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#endif + +/** + * @brief EXTI10..15 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI16_PRIORITY 6 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI17_PRIORITY 6 +#endif + +/** + * @brief EXTI18 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI18_PRIORITY 6 +#endif + +/** + * @brief EXTI19 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI19_PRIORITY 6 +#endif + +/** + * @brief EXTI20 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI20_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI20_PRIORITY 6 +#endif + +/** + * @brief EXTI21..22 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI21_22_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI21_22_PRIORITY 6 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/stm32_rcc.h b/os/hal/ports/STM32/STM32F37x/stm32_rcc.h index 4778f0e490..7dbc78beac 100644 --- a/os/hal/ports/STM32/STM32F37x/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32F37x/stm32_rcc.h @@ -1,1020 +1,1020 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f30x.h. - * - * @addtogroup STM32F37x_RCC - * @{ - */ - -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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); \ - (void)RCC->APB1ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - (void)RCC->APB1ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @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); \ - (void)RCC->APB2ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - (void)RCC->APB2ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} -/** @} */ - -/** - * @name ADC1 peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DAC1RST) - -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC2(lp) rccEnableAPB1(RCC_APB1ENR_DAC2EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC2() rccDisableAPB1(RCC_APB1ENR_DAC2EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC2() rccResetAPB1(RCC_APB1RSTR_DAC2RST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CANEN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CANEN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CANRST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) - -/** - * @brief Enables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name SDADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SDADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDADC1(lp) rccEnableAPB2(RCC_APB2ENR_SDADC1EN, lp) - -/** - * @brief Disables the SDADC1 peripheral clock. - * - * @api - */ -#define rccDisableSDADC1() rccDisableAPB2(RCC_APB2ENR_SDADC1EN) - -/** - * @brief Resets the SDADC1 peripheral. - * - * @api - */ -#define rccResetSDADC1() rccResetAPB2(RCC_APB2RSTR_SDADC1RST) - -/** - * @brief Enables the SDADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDADC2(lp) rccEnableAPB2(RCC_APB2ENR_SDADC2EN, lp) - -/** - * @brief Disables the SDADC2 peripheral clock. - * - * @api - */ -#define rccDisableSDADC2() rccDisableAPB2(RCC_APB2ENR_SDADC2EN) - -/** - * @brief Resets the SDADC2 peripheral. - * - * @api - */ -#define rccResetSDADC2() rccResetAPB2(RCC_APB2RSTR_SDADC2RST) - -/** - * @brief Enables the SDADC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDADC3(lp) rccEnableAPB2(RCC_APB2ENR_SDADC3EN, lp) - -/** - * @brief Disables the SDADC3 peripheral clock. - * - * @api - */ -#define rccDisableSDADC3() rccDisableAPB2(RCC_APB2ENR_SDADC3EN) - -/** - * @brief Resets the SDADC3 peripheral. - * - * @api - */ -#define rccResetSDADC3() rccResetAPB2(RCC_APB2RSTR_SDADC3RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM12 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) - -/** - * @brief Disables the TIM12 peripheral clock. - * - * @api - */ -#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) - -/** - * @brief Resets the TIM12 peripheral. - * - * @api - */ -#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) - -/** - * @brief Enables the TIM13 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) - -/** - * @brief Disables the TIM13 peripheral clock. - * - * @api - */ -#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) - -/** - * @brief Resets the TIM13 peripheral. - * - * @api - */ -#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) - -/** - * @brief Enables the TIM18 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM18(lp) rccEnableAPB1(RCC_APB1ENR_TIM18EN, lp) - -/** - * @brief Disables the TIM18 peripheral clock. - * - * @api - */ -#define rccDisableTIM18() rccDisableAPB1(RCC_APB1ENR_TIM18EN) - -/** - * @brief Resets the TIM18 peripheral. - * - * @api - */ -#define rccResetTIM18() rccResetAPB1(RCC_APB1RSTR_TIM18RST) - -/** - * @brief Enables the TIM19 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM19(lp) rccEnableAPB2(RCC_APB2ENR_TIM19EN, lp) - -/** - * @brief Disables the TIM19 peripheral clock. - * - * @api - */ -#define rccDisableTIM19() rccDisableAPB2(RCC_APB2ENR_TIM19EN) - -/** - * @brief Resets the TIM19 peripheral. - * - * @api - */ -#define rccResetTIM19() rccResetAPB2(RCC_APB2RSTR_TIM19RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/** - * @name CRC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f30x.h. + * + * @addtogroup STM32F37x_RCC + * @{ + */ + +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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); \ + (void)RCC->APB1ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + (void)RCC->APB1ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @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); \ + (void)RCC->APB2ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + (void)RCC->APB2ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} +/** @} */ + +/** + * @name ADC1 peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DAC1RST) + +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC2(lp) rccEnableAPB1(RCC_APB1ENR_DAC2EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC2() rccDisableAPB1(RCC_APB1ENR_DAC2EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC2() rccResetAPB1(RCC_APB1RSTR_DAC2RST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CANEN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CANEN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CANRST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) + +/** + * @brief Enables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name SDADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SDADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDADC1(lp) rccEnableAPB2(RCC_APB2ENR_SDADC1EN, lp) + +/** + * @brief Disables the SDADC1 peripheral clock. + * + * @api + */ +#define rccDisableSDADC1() rccDisableAPB2(RCC_APB2ENR_SDADC1EN) + +/** + * @brief Resets the SDADC1 peripheral. + * + * @api + */ +#define rccResetSDADC1() rccResetAPB2(RCC_APB2RSTR_SDADC1RST) + +/** + * @brief Enables the SDADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDADC2(lp) rccEnableAPB2(RCC_APB2ENR_SDADC2EN, lp) + +/** + * @brief Disables the SDADC2 peripheral clock. + * + * @api + */ +#define rccDisableSDADC2() rccDisableAPB2(RCC_APB2ENR_SDADC2EN) + +/** + * @brief Resets the SDADC2 peripheral. + * + * @api + */ +#define rccResetSDADC2() rccResetAPB2(RCC_APB2RSTR_SDADC2RST) + +/** + * @brief Enables the SDADC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDADC3(lp) rccEnableAPB2(RCC_APB2ENR_SDADC3EN, lp) + +/** + * @brief Disables the SDADC3 peripheral clock. + * + * @api + */ +#define rccDisableSDADC3() rccDisableAPB2(RCC_APB2ENR_SDADC3EN) + +/** + * @brief Resets the SDADC3 peripheral. + * + * @api + */ +#define rccResetSDADC3() rccResetAPB2(RCC_APB2RSTR_SDADC3RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM12 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) + +/** + * @brief Disables the TIM12 peripheral clock. + * + * @api + */ +#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) + +/** + * @brief Resets the TIM12 peripheral. + * + * @api + */ +#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) + +/** + * @brief Enables the TIM13 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) + +/** + * @brief Disables the TIM13 peripheral clock. + * + * @api + */ +#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) + +/** + * @brief Resets the TIM13 peripheral. + * + * @api + */ +#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) + +/** + * @brief Enables the TIM18 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM18(lp) rccEnableAPB1(RCC_APB1ENR_TIM18EN, lp) + +/** + * @brief Disables the TIM18 peripheral clock. + * + * @api + */ +#define rccDisableTIM18() rccDisableAPB1(RCC_APB1ENR_TIM18EN) + +/** + * @brief Resets the TIM18 peripheral. + * + * @api + */ +#define rccResetTIM18() rccResetAPB1(RCC_APB1RSTR_TIM18RST) + +/** + * @brief Enables the TIM19 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM19(lp) rccEnableAPB2(RCC_APB2ENR_TIM19EN, lp) + +/** + * @brief Disables the TIM19 peripheral clock. + * + * @api + */ +#define rccDisableTIM19() rccDisableAPB2(RCC_APB2ENR_TIM19EN) + +/** + * @brief Resets the TIM19 peripheral. + * + * @api + */ +#define rccResetTIM19() rccResetAPB2(RCC_APB2RSTR_TIM19RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/** + * @name CRC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F37x/stm32_registry.h b/os/hal/ports/STM32/STM32F37x/stm32_registry.h index 3a318fdf34..295a538c52 100644 --- a/os/hal/ports/STM32/STM32F37x/stm32_registry.h +++ b/os/hal/ports/STM32/STM32F37x/stm32_registry.h @@ -1,572 +1,572 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F37x/stm32_registry.h - * @brief STM32F37x capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F37x capabilities - * @{ - */ -/*===========================================================================*/ -/* STM32F373xC. */ -/*===========================================================================*/ -#if defined(STM32F373xC) || defined(__DOXYGEN__) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 TRUE -#define STM32_HAS_SDADC2 TRUE -#define STM32_HAS_SDADC3 TRUE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x1F800000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM18 TRUE -#define STM32_TIM18_IS_32BITS FALSE -#define STM32_TIM18_CHANNELS 0 - -#define STM32_HAS_TIM19 TRUE -#define STM32_TIM19_IS_32BITS FALSE -#define STM32_TIM19_CHANNELS 4 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F373xC) */ - -/*===========================================================================*/ -/* STM32F378xx. */ -/*===========================================================================*/ -#if defined(STM32F378xx) || defined(__DOXYGEN__) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 TRUE -#define STM32_HAS_SDADC2 TRUE -#define STM32_HAS_SDADC3 TRUE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x1F800000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM18 TRUE -#define STM32_TIM18_IS_32BITS FALSE -#define STM32_TIM18_CHANNELS 0 - -#define STM32_HAS_TIM19 TRUE -#define STM32_TIM19_IS_32BITS FALSE -#define STM32_TIM19_CHANNELS 4 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F378xx) */ -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F37x/stm32_registry.h + * @brief STM32F37x capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F37x capabilities + * @{ + */ +/*===========================================================================*/ +/* STM32F373xC. */ +/*===========================================================================*/ +#if defined(STM32F373xC) || defined(__DOXYGEN__) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 TRUE +#define STM32_HAS_SDADC2 TRUE +#define STM32_HAS_SDADC3 TRUE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x1F800000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM18 TRUE +#define STM32_TIM18_IS_32BITS FALSE +#define STM32_TIM18_CHANNELS 0 + +#define STM32_HAS_TIM19 TRUE +#define STM32_TIM19_IS_32BITS FALSE +#define STM32_TIM19_CHANNELS 4 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F373xC) */ + +/*===========================================================================*/ +/* STM32F378xx. */ +/*===========================================================================*/ +#if defined(STM32F378xx) || defined(__DOXYGEN__) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 TRUE +#define STM32_HAS_SDADC2 TRUE +#define STM32_HAS_SDADC3 TRUE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x1F800000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM18 TRUE +#define STM32_TIM18_IS_32BITS FALSE +#define STM32_TIM18_CHANNELS 0 + +#define STM32_HAS_TIM19 TRUE +#define STM32_TIM19_IS_32BITS FALSE +#define STM32_TIM19_CHANNELS 4 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F378xx) */ +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F3xx/hal_lld.c b/os/hal/ports/STM32/STM32F3xx/hal_lld.c index 42fa3a5d4c..b26774ad44 100644 --- a/os/hal/ports/STM32/STM32F3xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32F3xx/hal_lld.c @@ -1,233 +1,234 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/hal_lld.c - * @brief STM32F3xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f3xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB(~STM32_GPIO_EN_MASK); - rccResetAPB1(0xFFFFFFFF); - rccResetAPB2(0xFFFFFFFF); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); - -#if STM32_HAS_USB - /* USB IRQ relocated to not conflict with CAN.*/ - SYSCFG->CFGR1 |= SYSCFG_CFGR1_USB_IT_RMP; -#endif -} - -/** - * @brief STM32 clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. Clearing the register has to be postponed after HSI is the - new source.*/ - RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers finally cleared to reset values.*/ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - - /* Clock settings.*/ - RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | - STM32_PLLSRC | STM32_PPRE1 | STM32_PPRE2 | - STM32_HPRE; - RCC->CFGR2 = STM32_ADC34PRES | STM32_ADC12PRES | STM32_PREDIV; - RCC->CFGR3 = STM32_UART5SW | STM32_UART4SW | STM32_USART3SW | - STM32_USART2SW | STM32_I2C2SW | STM32_I2C1SW | - STM32_USART1SW; - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - /* Switches clock source.*/ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; /* Waits selection complete. */ -#endif - - /* After PLL activation because the special requirements for TIM1 and - TIM8 bits.*/ - RCC->CFGR3 |= STM32_HRTIM1SW | STM32_TIM8SW | STM32_TIM1SW; -#endif /* !STM32_NO_INIT */ -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/hal_lld.c + * @brief STM32F3xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f3xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB(~STM32_GPIO_EN_MASK); + rccResetAPB1(0xFFFFFFFF); + rccResetAPB2(0xFFFFFFFF); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); + +#if STM32_HAS_USB + /* USB IRQ relocated to not conflict with CAN.*/ + SYSCFG->CFGR1 |= SYSCFG_CFGR1_USB_IT_RMP; +#endif +} + +/** + * @brief STM32 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. Clearing the register has to be postponed after HSI is the + new source.*/ + RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers finally cleared to reset values.*/ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + + /* Clock settings.*/ + RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | + STM32_PLLSRC | STM32_PPRE1 | STM32_PPRE2 | + STM32_HPRE; + RCC->CFGR2 = STM32_ADC34PRES | STM32_ADC12PRES | STM32_PREDIV; + RCC->CFGR3 = STM32_UART5SW | STM32_UART4SW | STM32_USART3SW | + STM32_USART2SW | STM32_I2C2SW | STM32_I2C1SW | + STM32_USART1SW; + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + /* Switches clock source.*/ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; /* Waits selection complete. */ +#endif + + /* After PLL activation because the special requirements for TIM1 and + TIM8 bits.*/ + RCC->CFGR3 |= STM32_HRTIM1SW | STM32_TIM8SW | STM32_TIM1SW; +#endif /* !STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F3xx/hal_lld.h b/os/hal/ports/STM32/STM32F3xx/hal_lld.h index b379414c8a..2cc9e3e0c6 100644 --- a/os/hal/ports/STM32/STM32F3xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32F3xx/hal_lld.h @@ -1,1224 +1,1232 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/hal_lld.h - * @brief STM32F3xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32F301x8 for Analog & DSP devices. - * - STM32F302x8 for Analog & DSP devices. - * - STM32F302xC for Analog & DSP devices. - * - STM32F302xE for Analog & DSP devices. - * - STM32F303x8 for Analog & DSP devices. - * - STM32F303xC for Analog & DSP devices. - * - STM32F303xE for Analog & DSP devices. - * - STM32F318xx for Analog & DSP devices. - * - STM32F328xx for Analog & DSP devices. - * - STM32F334x8 for Analog & DSP devices. - * - STM32F358xx for Analog & DSP devices. - * - STM32F398xx for Analog & DSP devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32F301x8) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F301x8 Analog & DSP" - -#elif defined(STM32F302x8) -#define PLATFORM_NAME "STM32F302x8 Analog & DSP" - -#elif defined(STM32F302xC) -#define PLATFORM_NAME "STM32F302xC Analog & DSP" - -#elif defined(STM32F302xE) -#define PLATFORM_NAME "STM32F302xE Analog & DSP" - -#elif defined(STM32F303x8) -#define PLATFORM_NAME "STM32F303x8 Analog & DSP" - -#elif defined(STM32F303xC) -#define PLATFORM_NAME "STM32F303xC Analog & DSP" - -#elif defined(STM32F303xE) -#define PLATFORM_NAME "STM32F303xE Analog & DSP" - -#elif defined(STM32F318xx) -#define PLATFORM_NAME "STM32F318xx Analog & DSP" - -#elif defined(STM32F328xx) -#define PLATFORM_NAME "STM32F328xx Analog & DSP" - -#elif defined(STM32F334x8) -#define PLATFORM_NAME "STM32F334x8 Analog & DSP" - -#elif defined(STM32F358xx) -#define PLATFORM_NAME "STM32F358xx Analog & DSP" - -#elif defined(STM32F398xx) -#define PLATFORM_NAME "STM32F398xx Analog & DSP" - -#else -#error "STM32F3xx device not specified" -#endif -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 72000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @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 24000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 72000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 36000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 72000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 72000000 -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 8000000 /**< High speed internal clock. */ -#define STM32_LSICLK 40000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @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 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI/2. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is - HSE/PREDIV. */ - -#define STM32_USBPRE_DIV1P5 (0 << 22) /**< USB clock is PLLCLK/1.5. */ -#define STM32_USBPRE_DIV1 (1 << 22) /**< USB clock is PLLCLK/1. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_LSI (2 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (3 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as - RTC clock. */ -/** @} */ - -/** - * @name RCC_CFGR2 register bits definitions - * @{ - */ -#define STM32_PREDIV_MASK (15 << 0) /**< PREDIV divisor mask. */ -#define STM32_ADC12PRES_MASK (31 << 4) /**< ADC12 clock source mask. */ -#define STM32_ADC12PRES_NOCLOCK (0 << 4) /**< ADC12 clock is disabled. */ -#define STM32_ADC12PRES_DIV1 (16 << 4) /**< ADC12 clock is PLL/1. */ -#define STM32_ADC12PRES_DIV2 (17 << 4) /**< ADC12 clock is PLL/2. */ -#define STM32_ADC12PRES_DIV4 (18 << 4) /**< ADC12 clock is PLL/4. */ -#define STM32_ADC12PRES_DIV6 (19 << 4) /**< ADC12 clock is PLL/6. */ -#define STM32_ADC12PRES_DIV8 (20 << 4) /**< ADC12 clock is PLL/8. */ -#define STM32_ADC12PRES_DIV10 (21 << 4) /**< ADC12 clock is PLL/10. */ -#define STM32_ADC12PRES_DIV12 (22 << 4) /**< ADC12 clock is PLL/12. */ -#define STM32_ADC12PRES_DIV16 (23 << 4) /**< ADC12 clock is PLL/16. */ -#define STM32_ADC12PRES_DIV32 (24 << 4) /**< ADC12 clock is PLL/32. */ -#define STM32_ADC12PRES_DIV64 (25 << 4) /**< ADC12 clock is PLL/64. */ -#define STM32_ADC12PRES_DIV128 (26 << 4) /**< ADC12 clock is PLL/128. */ -#define STM32_ADC12PRES_DIV256 (27 << 4) /**< ADC12 clock is PLL/256. */ -#define STM32_ADC34PRES_MASK (31 << 9) /**< ADC34 clock source mask. */ -#define STM32_ADC34PRES_NOCLOCK (0 << 9) /**< ADC34 clock is disabled. */ -#define STM32_ADC34PRES_DIV1 (16 << 9) /**< ADC34 clock is PLL/1. */ -#define STM32_ADC34PRES_DIV2 (17 << 9) /**< ADC34 clock is PLL/2. */ -#define STM32_ADC34PRES_DIV4 (18 << 9) /**< ADC34 clock is PLL/4. */ -#define STM32_ADC34PRES_DIV6 (19 << 9) /**< ADC34 clock is PLL/6. */ -#define STM32_ADC34PRES_DIV8 (20 << 9) /**< ADC34 clock is PLL/8. */ -#define STM32_ADC34PRES_DIV10 (21 << 9) /**< ADC34 clock is PLL/10. */ -#define STM32_ADC34PRES_DIV12 (22 << 9) /**< ADC34 clock is PLL/12. */ -#define STM32_ADC34PRES_DIV16 (23 << 9) /**< ADC34 clock is PLL/16. */ -#define STM32_ADC34PRES_DIV32 (24 << 9) /**< ADC34 clock is PLL/32. */ -#define STM32_ADC34PRES_DIV64 (25 << 9) /**< ADC34 clock is PLL/64. */ -#define STM32_ADC34PRES_DIV128 (26 << 9) /**< ADC34 clock is PLL/128. */ -#define STM32_ADC34PRES_DIV256 (27 << 9) /**< ADC34 clock is PLL/256. */ -/** @} */ - -/** - * @name RCC_CFGR3 register bits definitions - * @{ - */ -#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ -#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ -#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ -#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ -#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ -#define STM32_I2C1SW_MASK (1 << 4) /**< I2C1 clock source mask. */ -#define STM32_I2C1SW_HSI (0 << 4) /**< I2C1 clock is HSI. */ -#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C1 clock is SYSCLK. */ -#define STM32_I2C2SW_MASK (1 << 5) /**< I2C2 clock source mask. */ -#define STM32_I2C2SW_HSI (0 << 5) /**< I2C2 clock is HSI. */ -#define STM32_I2C2SW_SYSCLK (1 << 5) /**< I2C2 clock is SYSCLK. */ -#define STM32_TIM1SW_MASK (1 << 8) /**< TIM1 clock source mask. */ -#define STM32_TIM1SW_PCLK2 (0 << 8) /**< TIM1 clock is PCLK2. */ -#define STM32_TIM1SW_PLLX2 (1 << 8) /**< TIM1 clock is PLL*2. */ -#define STM32_TIM8SW_MASK (1 << 9) /**< TIM8 clock source mask. */ -#define STM32_TIM8SW_PCLK2 (0 << 9) /**< TIM8 clock is PCLK2. */ -#define STM32_TIM8SW_PLLX2 (1 << 9) /**< TIM8 clock is PLL*2. */ -#define STM32_HRTIM1SW_MASK (1 << 12) /**< HRTIM1 clock source mask. */ -#define STM32_HRTIM1SW_PCLK2 (0 << 12) /**< HRTIM1 clock is PCLK2. */ -#define STM32_HRTIM1SW_PLLX2 (1 << 12) /**< HRTIM1 clock is PLL*2. */ -#define STM32_USART2SW_MASK (3 << 16) /**< USART2 clock source mask. */ -#define STM32_USART2SW_PCLK (0 << 16) /**< USART2 clock is PCLK. */ -#define STM32_USART2SW_SYSCLK (1 << 16) /**< USART2 clock is SYSCLK. */ -#define STM32_USART2SW_LSE (2 << 16) /**< USART2 clock is LSE. */ -#define STM32_USART2SW_HSI (3 << 16) /**< USART2 clock is HSI. */ -#define STM32_USART3SW_MASK (3 << 18) /**< USART3 clock source mask. */ -#define STM32_USART3SW_PCLK (0 << 18) /**< USART3 clock is PCLK. */ -#define STM32_USART3SW_SYSCLK (1 << 18) /**< USART3 clock is SYSCLK. */ -#define STM32_USART3SW_LSE (2 << 18) /**< USART3 clock is LSE. */ -#define STM32_USART3SW_HSI (3 << 18) /**< USART3 clock is HSI. */ -#define STM32_UART4SW_MASK (3 << 20) /**< USART4 clock source mask. */ -#define STM32_UART4SW_PCLK (0 << 20) /**< USART4 clock is PCLK. */ -#define STM32_UART4SW_SYSCLK (1 << 20) /**< USART4 clock is SYSCLK. */ -#define STM32_UART4SW_LSE (2 << 20) /**< USART4 clock is LSE. */ -#define STM32_UART4SW_HSI (3 << 20) /**< USART4 clock is HSI. */ -#define STM32_UART5SW_MASK (3 << 22) /**< USART5 clock source mask. */ -#define STM32_UART5SW_PCLK (0 << 22) /**< USART5 clock is PCLK. */ -#define STM32_UART5SW_SYSCLK (1 << 22) /**< USART5 clock is SYSCLK. */ -#define STM32_UART5SW_LSE (2 << 22) /**< USART5 clock is LSE. */ -#define STM32_UART5SW_HSI (3 << 22) /**< USART5 clock is HSI. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV_VALUE 1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 9 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief ADC12 prescaler value. - */ -#if !defined(STM32_ADC12PRES) || defined(__DOXYGEN__) -#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 -#endif - -/** - * @brief ADC34 prescaler value. - */ -#if !defined(STM32_ADC34PRES) || defined(__DOXYGEN__) -#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) -#define STM32_USART1SW STM32_USART1SW_PCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SW) || defined(__DOXYGEN__) -#define STM32_USART2SW STM32_USART2SW_PCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SW) || defined(__DOXYGEN__) -#define STM32_USART3SW STM32_USART3SW_PCLK -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SW) || defined(__DOXYGEN__) -#define STM32_UART4SW STM32_UART4SW_PCLK -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SW) || defined(__DOXYGEN__) -#define STM32_UART5SW STM32_UART5SW_PCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) -#define STM32_I2C1SW STM32_I2C1SW_SYSCLK -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SW) || defined(__DOXYGEN__) -#define STM32_I2C2SW STM32_I2C2SW_SYSCLK -#endif - -/** - * @brief TIM1 clock source. - */ -#if !defined(STM32_TIM1SW) || defined(__DOXYGEN__) -#define STM32_TIM1SW STM32_TIM1SW_PCLK2 -#endif - -/** - * @brief TIM8 clock source. - */ -#if !defined(STM32_TIM8SW) || defined(__DOXYGEN__) -#define STM32_TIM8SW STM32_TIM8SW_PCLK2 -#endif - -/** - * @brief HRTIM1 clock source. - */ -#if !defined(STM32_HRTIM1SW) || defined(__DOXYGEN__) -#define STM32_HRTIM1SW STM32_HRTIM1SW_PCLK2 -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif - -/** - * @brief USB clock setting. - */ -#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) -#define STM32_USB_CLOCK_REQUIRED TRUE -#endif - -/** - * @brief USB prescaler initialization. - */ -#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) -#define STM32_USBPRE STM32_USBPRE_DIV1P5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F3xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F3xx_MCUCONF not defined" -#endif - -/* Only some devices have strongly checked mcuconf.h files. Others will be - added gradually.*/ -#if (defined(STM32F303xC) || defined(STM32F303xE)) && \ - !defined(STM32F303_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F303_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_HSI -#error "HSI not enabled, required by STM32_USART1SW" -#endif - -#if STM32_USART2SW == STM32_USART2SW_HSI -#error "HSI not enabled, required by STM32_USART2SW" -#endif - -#if STM32_USART3SW == STM32_USART3SW_HSI -#error "HSI not enabled, required by STM32_USART3SW" -#endif - -#if STM32_UART4SW == STM32_UART4SW_HSI -#error "HSI not enabled, required by STM32_UART4SW" -#endif - -#if STM32_UART5SW == STM32_UART5SW_HSI -#error "HSI not enabled, required by STM32_UART5SW" -#endif - -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#error "HSI not enabled, required by STM32_I2C1SW" -#endif - -#if STM32_I2C2SW == STM32_I2C2SW_HSI -#error "HSI not enabled, required by STM32_I2C2SW" -#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_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if !defined(STM32_LSECLK) || (STM32_LSECLK == 0) -#error "STM32_LSECLK 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 !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" -#endif - -#if STM32_USART1SW == STM32_USART1SW_LSE -#error "LSE not enabled, required by STM32_USART1SW" -#endif - -#if STM32_USART2SW == STM32_USART2SW_LSE -#error "LSE not enabled, required by STM32_USART2SW" -#endif - -#if STM32_USART3SW == STM32_USART3SW_LSE -#error "LSE not enabled, required by STM32_USART3SW" -#endif - -#if STM32_UART4SW == STM32_UART4SW_LSE -#error "LSE not enabled, required by STM32_UART4SW" -#endif - -#if STM32_UART5SW == STM32_UART5SW_LSE -#error "LSE not enabled, required by STM32_UART5SW" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - (STM32_TIM1SW == STM32_TIM1SW_PLLX2) || \ - (STM32_TIM8SW == STM32_TIM8SW_PLLX2) || \ - (STM32_ADC12PRES != STM32_ADC12PRES_NOCLOCK) || \ - (STM32_ADC34PRES != STM32_ADC34PRES_NOCLOCK) || \ - STM32_USB_CLOCK_REQUIRED || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE prescaler setting check.*/ -#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) -#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) -#else -#error "invalid STM32_PREDIV value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL 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 - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC12 frequency. - */ -#if (STM32_ADC12PRES == STM32_ADC12PRES_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_ADC12CLK 0 -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV1 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 1) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV2 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 2) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV4 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 4) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV6 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 6) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV8 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 8) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV10 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 10) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV12 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 12) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV16 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 16) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV32 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 32) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV64 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 64) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV128 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 128) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV256 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 256) -#else -#error "invalid STM32_ADC12PRES value specified" -#endif - -/** - * @brief ADC34 frequency. - */ -#if (STM32_ADC34PRES == STM32_ADC34PRES_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_ADC34CLK 0 -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV1 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 1) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV2 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 2) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV4 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 4) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV6 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 6) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV8 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 8) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV10 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 10) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV12 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 12) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV16 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 16) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV32 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 32) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV64 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 64) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV128 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 128) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV256 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 256) -#else -#error "invalid STM32_ADC34PRES value specified" -#endif - -/* ADC12 frequency check.*/ -#if STM32_ADC12CLK > STM32_ADCCLK_MAX -#error "STM32_ADC12CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/* ADC34 frequency check.*/ -#if STM32_ADC34CLK > STM32_ADCCLK_MAX -#error "STM32_ADC34CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/** - * @brief I2C1 frequency. - */ -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#define STM32_I2C1CLK STM32_HSICLK -#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 frequency. - */ -#if STM32_I2C2SW == STM32_I2C2SW_HSI -#define STM32_I2C2CLK STM32_HSICLK -#elif STM32_I2C2SW == STM32_I2C2SW_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief USART1 frequency. - */ -#if STM32_USART1SW == STM32_USART1SW_PCLK -#define STM32_USART1CLK STM32_PCLK2 -#elif STM32_USART1SW == STM32_USART1SW_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SW == STM32_USART1SW_LSE -#define STM32_USART1CLK STM32_LSECLK -#elif STM32_USART1SW == STM32_USART1SW_HSI -#define STM32_USART1CLK STM32_HSICLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#if STM32_USART2SW == STM32_USART2SW_PCLK -#define STM32_USART2CLK STM32_PCLK1 -#elif STM32_USART2SW == STM32_USART2SW_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SW == STM32_USART2SW_LSE -#define STM32_USART2CLK STM32_LSECLK -#elif STM32_USART2SW == STM32_USART2SW_HSI -#define STM32_USART2CLK STM32_HSICLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 frequency. - */ -#if STM32_USART3SW == STM32_USART3SW_PCLK -#define STM32_USART3CLK STM32_PCLK1 -#elif STM32_USART3SW == STM32_USART3SW_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK -#elif STM32_USART3SW == STM32_USART3SW_LSE -#define STM32_USART3CLK STM32_LSECLK -#elif STM32_USART3SW == STM32_USART3SW_HSI -#define STM32_USART3CLK STM32_HSICLK -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief UART4 frequency. - */ -#if STM32_UART4SW == STM32_UART4SW_PCLK -#define STM32_UART4CLK STM32_PCLK1 -#elif STM32_UART4SW == STM32_UART4SW_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK -#elif STM32_UART4SW == STM32_UART4SW_LSE -#define STM32_UART4CLK STM32_LSECLK -#elif STM32_UART4SW == STM32_UART4SW_HSI -#define STM32_UART4CLK STM32_HSICLK -#else -#error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 frequency. - */ -#if STM32_UART5SW == STM32_UART5SW_PCLK -#define STM32_UART5CLK STM32_PCLK1 -#elif STM32_UART5SW == STM32_UART5SW_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK -#elif STM32_UART5SW == STM32_UART5SW_LSE -#define STM32_UART5CLK STM32_LSECLK -#elif STM32_UART5SW == STM32_UART5SW_HSI -#define STM32_UART5CLK STM32_HSICLK -#else -#error "invalid source selected for UART5 clock" -#endif - -/** - * @brief TIM1 frequency. - */ -#if STM32_TIM1SW == STM32_TIM1SW_PCLK2 -#if STM32_PPRE2 == STM32_PPRE2_DIV1 -#define STM32_TIM1CLK STM32_PCLK2 -#else -#define STM32_TIM1CLK (STM32_PCLK2 * 2) -#endif - -#elif STM32_TIM1SW == STM32_TIM1SW_PLLX2 -#if (STM32_SW != STM32_SW_PLL) || \ - (STM32_HPRE != STM32_HPRE_DIV1) || \ - (STM32_PPRE2 != STM32_PPRE2_DIV1) -#error "double clock mode cannot be activated for TIM1 under the current settings" -#endif -#define STM32_TIM1CLK (STM32_PLLCLKOUT * 2) - -#else -#error "invalid source selected for TIM1 clock" -#endif - -/** - * @brief TIM8 frequency. - */ -#if STM32_TIM8SW == STM32_TIM8SW_PCLK2 -#if STM32_PPRE2 == STM32_PPRE2_DIV1 -#define STM32_TIM8CLK STM32_PCLK2 -#else -#define STM32_TIM8CLK (STM32_PCLK2 * 2) -#endif - -#elif STM32_TIM8SW == STM32_TIM8SW_PLLX2 -#if (STM32_SW != STM32_SW_PLL) || \ - (STM32_HPRE != STM32_HPRE_DIV1) || \ - (STM32_PPRE2 != STM32_PPRE2_DIV1) -#error "double clock mode cannot be activated for TIM8 under the current settings" -#endif -#define STM32_TIM8CLK (STM32_PLLCLKOUT * 2) - -#else -#error "invalid source selected for TIM8 clock" -#endif - -/** - * @brief HRTIM1 frequency. - */ -#if STM32_HRTIM1SW == STM32_HRTIM1SW_PCLK2 -#if STM32_PPRE2 == STM32_PPRE2_DIV1 -#define STM32_HRTIM1CLK STM32_PCLK2 -#else -#define STM32_HRTIM1CLK (STM32_PCLK2 * 2) -#endif - -#elif STM32_HRTIM1SW == STM32_HRTIM1SW_PLLX2 -#if (STM32_SW != STM32_SW_PLL) || \ - (STM32_HPRE != STM32_HPRE_DIV1) || \ - (STM32_PPRE2 != STM32_PPRE2_DIV1) -#error "double clock mode cannot be activated for HRTIM1 under the current settings" -#endif -#define STM32_HRTIM1CLK (STM32_PLLCLKOUT * 2) - -#else -#error "invalid source selected for HRTIM1 clock" -#endif - -/** - * @brief Timers 2, 3, 4, 6, 7 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 1, 8, 15, 16, 17 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief USB frequency. - */ -#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) -#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) -#elif (STM32_USBPRE == STM32_USBPRE_DIV1) -#define STM32_USBCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_USBPRE value specified" -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#elif STM32_HCLK <= 48000000 -#define STM32_FLASHBITS 0x00000011 -#else -#define STM32_FLASHBITS 0x00000012 -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/hal_lld.h + * @brief STM32F3xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32F301x8 for Analog & DSP devices. + * - STM32F302x8 for Analog & DSP devices. + * - STM32F302xC for Analog & DSP devices. + * - STM32F302xE for Analog & DSP devices. + * - STM32F303x8 for Analog & DSP devices. + * - STM32F303xC for Analog & DSP devices. + * - STM32F303xE for Analog & DSP devices. + * - STM32F318xx for Analog & DSP devices. + * - STM32F328xx for Analog & DSP devices. + * - STM32F334x8 for Analog & DSP devices. + * - STM32F358xx for Analog & DSP devices. + * - STM32F398xx for Analog & DSP devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32F301x8) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F301x8 Analog & DSP" + +#elif defined(STM32F302x8) +#define PLATFORM_NAME "STM32F302x8 Analog & DSP" + +#elif defined(STM32F302xC) +#define PLATFORM_NAME "STM32F302xC Analog & DSP" + +#elif defined(STM32F302xE) +#define PLATFORM_NAME "STM32F302xE Analog & DSP" + +#elif defined(STM32F303x8) +#define PLATFORM_NAME "STM32F303x8 Analog & DSP" + +#elif defined(STM32F303xC) +#define PLATFORM_NAME "STM32F303xC Analog & DSP" + +#elif defined(STM32F303xE) +#define PLATFORM_NAME "STM32F303xE Analog & DSP" + +#elif defined(STM32F318xx) +#define PLATFORM_NAME "STM32F318xx Analog & DSP" + +#elif defined(STM32F328xx) +#define PLATFORM_NAME "STM32F328xx Analog & DSP" + +#elif defined(STM32F334x8) +#define PLATFORM_NAME "STM32F334x8 Analog & DSP" + +#elif defined(STM32F358xx) +#define PLATFORM_NAME "STM32F358xx Analog & DSP" + +#elif defined(STM32F398xx) +#define PLATFORM_NAME "STM32F398xx Analog & DSP" + +#else +#error "STM32F3xx device not specified" +#endif +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 72000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @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 24000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 72000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 36000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 72000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 72000000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 8000000 /**< High speed internal clock. */ +#define STM32_LSICLK 40000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @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 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI/2. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is + HSE/PREDIV. */ + +#define STM32_USBPRE_DIV1P5 (0 << 22) /**< USB clock is PLLCLK/1.5. */ +#define STM32_USBPRE_DIV1 (1 << 22) /**< USB clock is PLLCLK/1. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_LSI (2 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (3 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as + RTC clock. */ +/** @} */ + +/** + * @name RCC_CFGR2 register bits definitions + * @{ + */ +#define STM32_PREDIV_MASK (15 << 0) /**< PREDIV divisor mask. */ +#define STM32_ADC12PRES_MASK (31 << 4) /**< ADC12 clock source mask. */ +#define STM32_ADC12PRES_NOCLOCK (0 << 4) /**< ADC12 clock is disabled. */ +#define STM32_ADC12PRES_DIV1 (16 << 4) /**< ADC12 clock is PLL/1. */ +#define STM32_ADC12PRES_DIV2 (17 << 4) /**< ADC12 clock is PLL/2. */ +#define STM32_ADC12PRES_DIV4 (18 << 4) /**< ADC12 clock is PLL/4. */ +#define STM32_ADC12PRES_DIV6 (19 << 4) /**< ADC12 clock is PLL/6. */ +#define STM32_ADC12PRES_DIV8 (20 << 4) /**< ADC12 clock is PLL/8. */ +#define STM32_ADC12PRES_DIV10 (21 << 4) /**< ADC12 clock is PLL/10. */ +#define STM32_ADC12PRES_DIV12 (22 << 4) /**< ADC12 clock is PLL/12. */ +#define STM32_ADC12PRES_DIV16 (23 << 4) /**< ADC12 clock is PLL/16. */ +#define STM32_ADC12PRES_DIV32 (24 << 4) /**< ADC12 clock is PLL/32. */ +#define STM32_ADC12PRES_DIV64 (25 << 4) /**< ADC12 clock is PLL/64. */ +#define STM32_ADC12PRES_DIV128 (26 << 4) /**< ADC12 clock is PLL/128. */ +#define STM32_ADC12PRES_DIV256 (27 << 4) /**< ADC12 clock is PLL/256. */ +#define STM32_ADC34PRES_MASK (31 << 9) /**< ADC34 clock source mask. */ +#define STM32_ADC34PRES_NOCLOCK (0 << 9) /**< ADC34 clock is disabled. */ +#define STM32_ADC34PRES_DIV1 (16 << 9) /**< ADC34 clock is PLL/1. */ +#define STM32_ADC34PRES_DIV2 (17 << 9) /**< ADC34 clock is PLL/2. */ +#define STM32_ADC34PRES_DIV4 (18 << 9) /**< ADC34 clock is PLL/4. */ +#define STM32_ADC34PRES_DIV6 (19 << 9) /**< ADC34 clock is PLL/6. */ +#define STM32_ADC34PRES_DIV8 (20 << 9) /**< ADC34 clock is PLL/8. */ +#define STM32_ADC34PRES_DIV10 (21 << 9) /**< ADC34 clock is PLL/10. */ +#define STM32_ADC34PRES_DIV12 (22 << 9) /**< ADC34 clock is PLL/12. */ +#define STM32_ADC34PRES_DIV16 (23 << 9) /**< ADC34 clock is PLL/16. */ +#define STM32_ADC34PRES_DIV32 (24 << 9) /**< ADC34 clock is PLL/32. */ +#define STM32_ADC34PRES_DIV64 (25 << 9) /**< ADC34 clock is PLL/64. */ +#define STM32_ADC34PRES_DIV128 (26 << 9) /**< ADC34 clock is PLL/128. */ +#define STM32_ADC34PRES_DIV256 (27 << 9) /**< ADC34 clock is PLL/256. */ +/** @} */ + +/** + * @name RCC_CFGR3 register bits definitions + * @{ + */ +#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ +#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ +#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ +#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ +#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ +#define STM32_I2C1SW_MASK (1 << 4) /**< I2C1 clock source mask. */ +#define STM32_I2C1SW_HSI (0 << 4) /**< I2C1 clock is HSI. */ +#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C1 clock is SYSCLK. */ +#define STM32_I2C2SW_MASK (1 << 5) /**< I2C2 clock source mask. */ +#define STM32_I2C2SW_HSI (0 << 5) /**< I2C2 clock is HSI. */ +#define STM32_I2C2SW_SYSCLK (1 << 5) /**< I2C2 clock is SYSCLK. */ +#define STM32_TIM1SW_MASK (1 << 8) /**< TIM1 clock source mask. */ +#define STM32_TIM1SW_PCLK2 (0 << 8) /**< TIM1 clock is PCLK2. */ +#define STM32_TIM1SW_PLLX2 (1 << 8) /**< TIM1 clock is PLL*2. */ +#define STM32_TIM8SW_MASK (1 << 9) /**< TIM8 clock source mask. */ +#define STM32_TIM8SW_PCLK2 (0 << 9) /**< TIM8 clock is PCLK2. */ +#define STM32_TIM8SW_PLLX2 (1 << 9) /**< TIM8 clock is PLL*2. */ +#define STM32_HRTIM1SW_MASK (1 << 12) /**< HRTIM1 clock source mask. */ +#define STM32_HRTIM1SW_PCLK2 (0 << 12) /**< HRTIM1 clock is PCLK2. */ +#define STM32_HRTIM1SW_PLLX2 (1 << 12) /**< HRTIM1 clock is PLL*2. */ +#define STM32_USART2SW_MASK (3 << 16) /**< USART2 clock source mask. */ +#define STM32_USART2SW_PCLK (0 << 16) /**< USART2 clock is PCLK. */ +#define STM32_USART2SW_SYSCLK (1 << 16) /**< USART2 clock is SYSCLK. */ +#define STM32_USART2SW_LSE (2 << 16) /**< USART2 clock is LSE. */ +#define STM32_USART2SW_HSI (3 << 16) /**< USART2 clock is HSI. */ +#define STM32_USART3SW_MASK (3 << 18) /**< USART3 clock source mask. */ +#define STM32_USART3SW_PCLK (0 << 18) /**< USART3 clock is PCLK. */ +#define STM32_USART3SW_SYSCLK (1 << 18) /**< USART3 clock is SYSCLK. */ +#define STM32_USART3SW_LSE (2 << 18) /**< USART3 clock is LSE. */ +#define STM32_USART3SW_HSI (3 << 18) /**< USART3 clock is HSI. */ +#define STM32_UART4SW_MASK (3 << 20) /**< USART4 clock source mask. */ +#define STM32_UART4SW_PCLK (0 << 20) /**< USART4 clock is PCLK. */ +#define STM32_UART4SW_SYSCLK (1 << 20) /**< USART4 clock is SYSCLK. */ +#define STM32_UART4SW_LSE (2 << 20) /**< USART4 clock is LSE. */ +#define STM32_UART4SW_HSI (3 << 20) /**< USART4 clock is HSI. */ +#define STM32_UART5SW_MASK (3 << 22) /**< USART5 clock source mask. */ +#define STM32_UART5SW_PCLK (0 << 22) /**< USART5 clock is PCLK. */ +#define STM32_UART5SW_SYSCLK (1 << 22) /**< USART5 clock is SYSCLK. */ +#define STM32_UART5SW_LSE (2 << 22) /**< USART5 clock is LSE. */ +#define STM32_UART5SW_HSI (3 << 22) /**< USART5 clock is HSI. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV_VALUE 1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 9 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief ADC12 prescaler value. + */ +#if !defined(STM32_ADC12PRES) || defined(__DOXYGEN__) +#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 +#endif + +/** + * @brief ADC34 prescaler value. + */ +#if !defined(STM32_ADC34PRES) || defined(__DOXYGEN__) +#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) +#define STM32_USART1SW STM32_USART1SW_PCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SW) || defined(__DOXYGEN__) +#define STM32_USART2SW STM32_USART2SW_PCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SW) || defined(__DOXYGEN__) +#define STM32_USART3SW STM32_USART3SW_PCLK +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SW) || defined(__DOXYGEN__) +#define STM32_UART4SW STM32_UART4SW_PCLK +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SW) || defined(__DOXYGEN__) +#define STM32_UART5SW STM32_UART5SW_PCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SW) || defined(__DOXYGEN__) +#define STM32_I2C2SW STM32_I2C2SW_SYSCLK +#endif + +/** + * @brief TIM1 clock source. + */ +#if !defined(STM32_TIM1SW) || defined(__DOXYGEN__) +#define STM32_TIM1SW STM32_TIM1SW_PCLK2 +#endif + +/** + * @brief TIM8 clock source. + */ +#if !defined(STM32_TIM8SW) || defined(__DOXYGEN__) +#define STM32_TIM8SW STM32_TIM8SW_PCLK2 +#endif + +/** + * @brief HRTIM1 clock source. + */ +#if !defined(STM32_HRTIM1SW) || defined(__DOXYGEN__) +#define STM32_HRTIM1SW STM32_HRTIM1SW_PCLK2 +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif + +/** + * @brief USB clock setting. + */ +#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) +#define STM32_USB_CLOCK_REQUIRED TRUE +#endif + +/** + * @brief USB prescaler initialization. + */ +#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) +#define STM32_USBPRE STM32_USBPRE_DIV1P5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F3xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F3xx_MCUCONF not defined" +#endif + +/* Only some devices have strongly checked mcuconf.h files. Others will be + added gradually.*/ +#if (defined(STM32F303xC) || defined(STM32F303xE)) && \ + !defined(STM32F303_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F303_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_HSI +#error "HSI not enabled, required by STM32_USART1SW" +#endif + +#if STM32_USART2SW == STM32_USART2SW_HSI +#error "HSI not enabled, required by STM32_USART2SW" +#endif + +#if STM32_USART3SW == STM32_USART3SW_HSI +#error "HSI not enabled, required by STM32_USART3SW" +#endif + +#if STM32_UART4SW == STM32_UART4SW_HSI +#error "HSI not enabled, required by STM32_UART4SW" +#endif + +#if STM32_UART5SW == STM32_UART5SW_HSI +#error "HSI not enabled, required by STM32_UART5SW" +#endif + +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#error "HSI not enabled, required by STM32_I2C1SW" +#endif + +#if STM32_I2C2SW == STM32_I2C2SW_HSI +#error "HSI not enabled, required by STM32_I2C2SW" +#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_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if !defined(STM32_LSECLK) || (STM32_LSECLK == 0) +#error "STM32_LSECLK 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 !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" +#endif + +#if STM32_USART1SW == STM32_USART1SW_LSE +#error "LSE not enabled, required by STM32_USART1SW" +#endif + +#if STM32_USART2SW == STM32_USART2SW_LSE +#error "LSE not enabled, required by STM32_USART2SW" +#endif + +#if STM32_USART3SW == STM32_USART3SW_LSE +#error "LSE not enabled, required by STM32_USART3SW" +#endif + +#if STM32_UART4SW == STM32_UART4SW_LSE +#error "LSE not enabled, required by STM32_UART4SW" +#endif + +#if STM32_UART5SW == STM32_UART5SW_LSE +#error "LSE not enabled, required by STM32_UART5SW" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + (STM32_TIM1SW == STM32_TIM1SW_PLLX2) || \ + (STM32_TIM8SW == STM32_TIM8SW_PLLX2) || \ + (STM32_ADC12PRES != STM32_ADC12PRES_NOCLOCK) || \ + (STM32_ADC34PRES != STM32_ADC34PRES_NOCLOCK) || \ + STM32_USB_CLOCK_REQUIRED || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE prescaler setting check.*/ +#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) +#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) +#else +#error "invalid STM32_PREDIV value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL 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 + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC12 frequency. + */ +#if (STM32_ADC12PRES == STM32_ADC12PRES_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_ADC12CLK 0 +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV1 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 1) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV2 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 2) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV4 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 4) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV6 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 6) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV8 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 8) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV10 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 10) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV12 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 12) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV16 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 16) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV32 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 32) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV64 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 64) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV128 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 128) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV256 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 256) +#else +#error "invalid STM32_ADC12PRES value specified" +#endif + +/** + * @brief ADC34 frequency. + */ +#if (STM32_ADC34PRES == STM32_ADC34PRES_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_ADC34CLK 0 +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV1 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 1) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV2 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 2) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV4 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 4) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV6 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 6) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV8 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 8) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV10 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 10) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV12 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 12) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV16 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 16) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV32 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 32) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV64 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 64) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV128 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 128) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV256 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 256) +#else +#error "invalid STM32_ADC34PRES value specified" +#endif + +/* ADC12 frequency check.*/ +#if STM32_ADC12CLK > STM32_ADCCLK_MAX +#error "STM32_ADC12CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/* ADC34 frequency check.*/ +#if STM32_ADC34CLK > STM32_ADCCLK_MAX +#error "STM32_ADC34CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/** + * @brief I2C1 frequency. + */ +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#define STM32_I2C1CLK STM32_HSICLK +#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 frequency. + */ +#if STM32_I2C2SW == STM32_I2C2SW_HSI +#define STM32_I2C2CLK STM32_HSICLK +#elif STM32_I2C2SW == STM32_I2C2SW_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief USART1 frequency. + */ +#if STM32_USART1SW == STM32_USART1SW_PCLK +#define STM32_USART1CLK STM32_PCLK2 +#elif STM32_USART1SW == STM32_USART1SW_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SW == STM32_USART1SW_LSE +#define STM32_USART1CLK STM32_LSECLK +#elif STM32_USART1SW == STM32_USART1SW_HSI +#define STM32_USART1CLK STM32_HSICLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#if STM32_USART2SW == STM32_USART2SW_PCLK +#define STM32_USART2CLK STM32_PCLK1 +#elif STM32_USART2SW == STM32_USART2SW_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SW == STM32_USART2SW_LSE +#define STM32_USART2CLK STM32_LSECLK +#elif STM32_USART2SW == STM32_USART2SW_HSI +#define STM32_USART2CLK STM32_HSICLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 frequency. + */ +#if STM32_USART3SW == STM32_USART3SW_PCLK +#define STM32_USART3CLK STM32_PCLK1 +#elif STM32_USART3SW == STM32_USART3SW_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK +#elif STM32_USART3SW == STM32_USART3SW_LSE +#define STM32_USART3CLK STM32_LSECLK +#elif STM32_USART3SW == STM32_USART3SW_HSI +#define STM32_USART3CLK STM32_HSICLK +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief UART4 frequency. + */ +#if STM32_UART4SW == STM32_UART4SW_PCLK +#define STM32_UART4CLK STM32_PCLK1 +#elif STM32_UART4SW == STM32_UART4SW_SYSCLK +#define STM32_UART4CLK STM32_SYSCLK +#elif STM32_UART4SW == STM32_UART4SW_LSE +#define STM32_UART4CLK STM32_LSECLK +#elif STM32_UART4SW == STM32_UART4SW_HSI +#define STM32_UART4CLK STM32_HSICLK +#else +#error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 frequency. + */ +#if STM32_UART5SW == STM32_UART5SW_PCLK +#define STM32_UART5CLK STM32_PCLK1 +#elif STM32_UART5SW == STM32_UART5SW_SYSCLK +#define STM32_UART5CLK STM32_SYSCLK +#elif STM32_UART5SW == STM32_UART5SW_LSE +#define STM32_UART5CLK STM32_LSECLK +#elif STM32_UART5SW == STM32_UART5SW_HSI +#define STM32_UART5CLK STM32_HSICLK +#else +#error "invalid source selected for UART5 clock" +#endif + +/** + * @brief TIM1 frequency. + */ +#if STM32_TIM1SW == STM32_TIM1SW_PCLK2 +#if STM32_PPRE2 == STM32_PPRE2_DIV1 +#define STM32_TIM1CLK STM32_PCLK2 +#else +#define STM32_TIM1CLK (STM32_PCLK2 * 2) +#endif + +#elif STM32_TIM1SW == STM32_TIM1SW_PLLX2 +#if (STM32_SW != STM32_SW_PLL) || \ + (STM32_HPRE != STM32_HPRE_DIV1) || \ + (STM32_PPRE2 != STM32_PPRE2_DIV1) +#error "double clock mode cannot be activated for TIM1 under the current settings" +#endif +#define STM32_TIM1CLK (STM32_PLLCLKOUT * 2) + +#else +#error "invalid source selected for TIM1 clock" +#endif + +/** + * @brief TIM8 frequency. + */ +#if STM32_TIM8SW == STM32_TIM8SW_PCLK2 +#if STM32_PPRE2 == STM32_PPRE2_DIV1 +#define STM32_TIM8CLK STM32_PCLK2 +#else +#define STM32_TIM8CLK (STM32_PCLK2 * 2) +#endif + +#elif STM32_TIM8SW == STM32_TIM8SW_PLLX2 +#if (STM32_SW != STM32_SW_PLL) || \ + (STM32_HPRE != STM32_HPRE_DIV1) || \ + (STM32_PPRE2 != STM32_PPRE2_DIV1) +#error "double clock mode cannot be activated for TIM8 under the current settings" +#endif +#define STM32_TIM8CLK (STM32_PLLCLKOUT * 2) + +#else +#error "invalid source selected for TIM8 clock" +#endif + +/** + * @brief HRTIM1 frequency. + */ +#if STM32_HRTIM1SW == STM32_HRTIM1SW_PCLK2 +#if STM32_PPRE2 == STM32_PPRE2_DIV1 +#define STM32_HRTIM1CLK STM32_PCLK2 +#else +#define STM32_HRTIM1CLK (STM32_PCLK2 * 2) +#endif + +#elif STM32_HRTIM1SW == STM32_HRTIM1SW_PLLX2 +#if (STM32_SW != STM32_SW_PLL) || \ + (STM32_HPRE != STM32_HPRE_DIV1) || \ + (STM32_PPRE2 != STM32_PPRE2_DIV1) +#error "double clock mode cannot be activated for HRTIM1 under the current settings" +#endif +#define STM32_HRTIM1CLK (STM32_PLLCLKOUT * 2) + +#else +#error "invalid source selected for HRTIM1 clock" +#endif + +/** + * @brief Timers 2, 3, 4, 6, 7 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 1, 8, 15, 16, 17 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief USB frequency. + */ +#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) +#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) +#elif (STM32_USBPRE == STM32_USBPRE_DIV1) +#define STM32_USBCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_USBPRE value specified" +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#elif STM32_HCLK <= 48000000 +#define STM32_FLASHBITS 0x00000011 +#else +#define STM32_FLASHBITS 0x00000012 +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F3xx/platform.mk b/os/hal/ports/STM32/STM32F3xx/platform.mk index 67673bd59f..2a7063a5a7 100644 --- a/os/hal/ports/STM32/STM32F3xx/platform.mk +++ b/os/hal/ports/STM32/STM32F3xx/platform.mk @@ -1,44 +1,44 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F3xx/stm32_isr.c b/os/hal/ports/STM32/STM32F3xx/stm32_isr.c index 9b43cf7108..f2112492e5 100644 --- a/os/hal/ports/STM32/STM32F3xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32F3xx/stm32_isr.c @@ -1,382 +1,382 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/stm32_isr.c - * @brief STM32F3xx ISR handler code. - * - * @addtogroup STM32F3xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_EXTI0_HANDLER) -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 0); - EXTI->PR = pr; - - exti_serve_irq(pr, 0); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI1_HANDLER) -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 1); - EXTI->PR = pr; - - exti_serve_irq(pr, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_HANDLER) -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 2); - EXTI->PR = pr; - - exti_serve_irq(pr, 2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI3_HANDLER) -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 3); - EXTI->PR = pr; - - exti_serve_irq(pr, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_HANDLER) -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 4); - EXTI->PR = pr; - - exti_serve_irq(pr, 4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | - (1U << 9)); - EXTI->PR = pr; - - exti_serve_irq(pr, 5); - exti_serve_irq(pr, 6); - exti_serve_irq(pr, 7); - exti_serve_irq(pr, 8); - exti_serve_irq(pr, 9); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | - (1U << 14) | (1U << 15)); - EXTI->PR = pr; - - exti_serve_irq(pr, 10); - exti_serve_irq(pr, 11); - exti_serve_irq(pr, 12); - exti_serve_irq(pr, 13); - exti_serve_irq(pr, 14); - exti_serve_irq(pr, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif -#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ - -#if HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM || defined(__DOXYGEN__) -/** - * @brief TIM1-BRK, TIM15 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorA0) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_GPT -#if STM32_GPT_USE_TIM15 - gpt_lld_serve_interrupt(&GPTD15); -#endif -#endif -#if HAL_USE_ICU -#if STM32_ICU_USE_TIM15 - icu_lld_serve_interrupt(&ICUD15); -#endif -#endif -#if HAL_USE_PWM -#if STM32_PWM_USE_TIM15 - pwm_lld_serve_interrupt(&PWMD15); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief TIM1-UP, TIM16 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorA4) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_GPT -#if STM32_GPT_USE_TIM1 - gpt_lld_serve_interrupt(&GPTD1); -#endif -#if STM32_GPT_USE_TIM16 - gpt_lld_serve_interrupt(&GPTD16); -#endif -#endif -#if HAL_USE_ICU -#if STM32_ICU_USE_TIM1 - icu_lld_serve_interrupt(&ICUD1); -#endif -#endif -#if HAL_USE_PWM -#if STM32_PWM_USE_TIM1 - pwm_lld_serve_interrupt(&PWMD1); -#endif -#if STM32_PWM_USE_TIM16 - pwm_lld_serve_interrupt(&PWMD16); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief TIM1-TRG-COM, TIM17 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorA8) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_GPT -#if STM32_GPT_USE_TIM17 - gpt_lld_serve_interrupt(&GPTD17); -#endif -#endif -#if HAL_USE_ICU - /* Not used by ICU.*/ -#endif -#if HAL_USE_PWM -#if STM32_PWM_USE_TIM17 - pwm_lld_serve_interrupt(&PWMD17); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief TIM1-CC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorAC) { - - OSAL_IRQ_PROLOGUE(); - -#if HAL_USE_GPT - /* Not used by GPT.*/ -#endif -#if HAL_USE_ICU -#if STM32_ICU_USE_TIM1 - icu_lld_serve_interrupt(&ICUD1); -#endif -#endif -#if HAL_USE_PWM -#if STM32_PWM_USE_TIM1 - pwm_lld_serve_interrupt(&PWMD1); -#endif -#endif - - OSAL_IRQ_EPILOGUE(); -} -#endif /* HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - -#if HAL_USE_PAL - nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); - nvicEnableVector(EXTI2_TSC_IRQn, STM32_IRQ_EXTI2_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); -#endif -#if HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM || defined(__DOXYGEN__) - nvicEnableVector(TIM1_BRK_TIM15_IRQn, STM32_IRQ_TIM1_BRK_TIM15_PRIORITY); - nvicEnableVector(TIM1_UP_TIM16_IRQn, STM32_IRQ_TIM1_UP_TIM16_PRIORITY); - nvicEnableVector(TIM1_TRG_COM_TIM17_IRQn, STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY); - nvicEnableVector(TIM1_CC_IRQn, STM32_IRQ_TIM1_CC_PRIORITY); -#endif -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - -#if HAL_USE_PAL - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_TSC_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); -#endif -#if HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM || defined(__DOXYGEN__) - nvicDisableVector(TIM1_BRK_TIM15_IRQn); - nvicDisableVector(TIM1_UP_TIM16_IRQn); - nvicDisableVector(TIM1_TRG_COM_TIM17_IRQn); - nvicDisableVector(TIM1_CC_IRQn); -#endif -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/stm32_isr.c + * @brief STM32F3xx ISR handler code. + * + * @addtogroup STM32F3xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_EXTI0_HANDLER) +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 0); + EXTI->PR = pr; + + exti_serve_irq(pr, 0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI1_HANDLER) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 1); + EXTI->PR = pr; + + exti_serve_irq(pr, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_HANDLER) +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 2); + EXTI->PR = pr; + + exti_serve_irq(pr, 2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI3_HANDLER) +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 3); + EXTI->PR = pr; + + exti_serve_irq(pr, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_HANDLER) +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 4); + EXTI->PR = pr; + + exti_serve_irq(pr, 4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | + (1U << 9)); + EXTI->PR = pr; + + exti_serve_irq(pr, 5); + exti_serve_irq(pr, 6); + exti_serve_irq(pr, 7); + exti_serve_irq(pr, 8); + exti_serve_irq(pr, 9); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | + (1U << 14) | (1U << 15)); + EXTI->PR = pr; + + exti_serve_irq(pr, 10); + exti_serve_irq(pr, 11); + exti_serve_irq(pr, 12); + exti_serve_irq(pr, 13); + exti_serve_irq(pr, 14); + exti_serve_irq(pr, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ + +#if HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM || defined(__DOXYGEN__) +/** + * @brief TIM1-BRK, TIM15 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorA0) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_GPT +#if STM32_GPT_USE_TIM15 + gpt_lld_serve_interrupt(&GPTD15); +#endif +#endif +#if HAL_USE_ICU +#if STM32_ICU_USE_TIM15 + icu_lld_serve_interrupt(&ICUD15); +#endif +#endif +#if HAL_USE_PWM +#if STM32_PWM_USE_TIM15 + pwm_lld_serve_interrupt(&PWMD15); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief TIM1-UP, TIM16 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorA4) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_GPT +#if STM32_GPT_USE_TIM1 + gpt_lld_serve_interrupt(&GPTD1); +#endif +#if STM32_GPT_USE_TIM16 + gpt_lld_serve_interrupt(&GPTD16); +#endif +#endif +#if HAL_USE_ICU +#if STM32_ICU_USE_TIM1 + icu_lld_serve_interrupt(&ICUD1); +#endif +#endif +#if HAL_USE_PWM +#if STM32_PWM_USE_TIM1 + pwm_lld_serve_interrupt(&PWMD1); +#endif +#if STM32_PWM_USE_TIM16 + pwm_lld_serve_interrupt(&PWMD16); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief TIM1-TRG-COM, TIM17 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorA8) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_GPT +#if STM32_GPT_USE_TIM17 + gpt_lld_serve_interrupt(&GPTD17); +#endif +#endif +#if HAL_USE_ICU + /* Not used by ICU.*/ +#endif +#if HAL_USE_PWM +#if STM32_PWM_USE_TIM17 + pwm_lld_serve_interrupt(&PWMD17); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief TIM1-CC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorAC) { + + OSAL_IRQ_PROLOGUE(); + +#if HAL_USE_GPT + /* Not used by GPT.*/ +#endif +#if HAL_USE_ICU +#if STM32_ICU_USE_TIM1 + icu_lld_serve_interrupt(&ICUD1); +#endif +#endif +#if HAL_USE_PWM +#if STM32_PWM_USE_TIM1 + pwm_lld_serve_interrupt(&PWMD1); +#endif +#endif + + OSAL_IRQ_EPILOGUE(); +} +#endif /* HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + +#if HAL_USE_PAL + nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); + nvicEnableVector(EXTI2_TSC_IRQn, STM32_IRQ_EXTI2_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); +#endif +#if HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM || defined(__DOXYGEN__) + nvicEnableVector(TIM1_BRK_TIM15_IRQn, STM32_IRQ_TIM1_BRK_TIM15_PRIORITY); + nvicEnableVector(TIM1_UP_TIM16_IRQn, STM32_IRQ_TIM1_UP_TIM16_PRIORITY); + nvicEnableVector(TIM1_TRG_COM_TIM17_IRQn, STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY); + nvicEnableVector(TIM1_CC_IRQn, STM32_IRQ_TIM1_CC_PRIORITY); +#endif +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +#if HAL_USE_PAL + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_TSC_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); +#endif +#if HAL_USE_GPT || HAL_USE_ICU || HAL_USE_PWM || defined(__DOXYGEN__) + nvicDisableVector(TIM1_BRK_TIM15_IRQn); + nvicDisableVector(TIM1_UP_TIM16_IRQn); + nvicDisableVector(TIM1_TRG_COM_TIM17_IRQn); + nvicDisableVector(TIM1_CC_IRQn); +#endif +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F3xx/stm32_isr.h b/os/hal/ports/STM32/STM32F3xx/stm32_isr.h index 38968038e2..67a77e1b55 100644 --- a/os/hal/ports/STM32/STM32F3xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F3xx/stm32_isr.h @@ -1,400 +1,400 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/stm32_isr.h - * @brief STM32F3xx ISR handler header. - * - * @addtogroup STM32F3xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 - -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 - -#define STM32_I2C3_EVENT_HANDLER Vector160 -#define STM32_I2C3_ERROR_HANDLER Vector164 -#define STM32_I2C3_EVENT_NUMBER 72 -#define STM32_I2C3_ERROR_NUMBER 73 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER VectorA4 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_CC_HANDLER VectorF8 -#define STM32_TIM15_HANDLER VectorA0 /* Note: same as STM32_TIM1_BRK */ -#define STM32_TIM16_HANDLER VectorA4 /* Note: same as STM32_TIM1_UP */ -#define STM32_TIM17_HANDLER VectorA8 /* Note: same as STM32_TIM1_TRG_COM */ -#define STM32_TIM20_UP_HANDLER Vector178 -#define STM32_TIM20_CC_HANDLER Vector180 - -#define STM32_TIM1_UP_NUMBER 25 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_CC_NUMBER 46 -#define STM32_TIM15_NUMBER 24 /* Note: same as STM32_TIM1_BRK */ -#define STM32_TIM16_NUMBER 25 /* Note: same as STM32_TIM1_UP */ -#define STM32_TIM17_NUMBER 26 /* Note: same as STM32_TIM1_TRG_COM */ -#define STM32_TIM20_UP_NUMBER 78 -#define STM32_TIM20_CC_NUMBER 80 - -/* - * HRTIM units (F334) - */ -#define STM32_HRTIM_MASTER_HANDLER Vector14C -#define STM32_HRTIM_TIMA_HANDLER Vector150 -#define STM32_HRTIM_TIMB_HANDLER Vector154 -#define STM32_HRTIM_TIMC_HANDLER Vector158 -#define STM32_HRTIM_TIMD_HANDLER Vector15C -#define STM32_HRTIM_TIME_HANDLER Vector160 -#define STM32_HRTIM_FLT_HANDLER Vector164 - -#define STM32_HRTIM_MASTER_NUMBER 67 -#define STM32_HRTIM_TIMA_NUMBER 68 -#define STM32_HRTIM_TIMB_NUMBER 69 -#define STM32_HRTIM_TIMC_NUMBER 70 -#define STM32_HRTIM_TIMD_NUMBER 71 -#define STM32_HRTIM_TIME_NUMBER 72 -#define STM32_HRTIM_FLT_NUMBER 73 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 - -/* - * USB units. - */ -#define STM32_USB1_HP_HANDLER Vector168 -#define STM32_USB1_LP_HANDLER Vector16C - -#define STM32_USB1_HP_NUMBER 74 -#define STM32_USB1_LP_NUMBER 75 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI0_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI1_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI2_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI3_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI4_PRIORITY 6 -#endif - -/** - * @brief EXTI5..9 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#endif - -/** - * @brief EXTI10..15 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI16_PRIORITY 6 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI17_PRIORITY 6 -#endif - -/** - * @brief EXTI18 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI18_PRIORITY 6 -#endif - -/** - * @brief EXTI19 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI19_PRIORITY 6 -#endif - -/** - * @brief EXTI20 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI20_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI20_PRIORITY 6 -#endif - -/** - * @brief EXTI21,22,29 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI21_22_29_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 -#endif - -/** - * @brief EXTI30..32 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI30_32_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI30_32_PRIORITY 6 -#endif - -/** - * @brief EXTI33 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI33_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI33_PRIORITY 6 -#endif - -/** - * @brief TIM1-BRK, TIM15 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_TIM1_BRK_TIM15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#endif - -/** - * @brief TIM1-UP, TIM16 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_TIM1_UP_TIM16_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#endif - -/** - * @brief TIM1-TRG-COM, TIM17 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#endif - -/** - * @brief TIM1-CC interrupt priority level setting. - */ -#if !defined(STM32_IRQ_TIM1_CC_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_TIM1_CC_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* IRQ priority checks.*/ -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI0_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI0_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI1_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI1_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI2_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI2_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI3_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI3_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI4_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI4_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI5_9_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI5_9_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI10_15_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI10_15_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI16_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI16_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI17_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI17_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI18_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI18_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI19_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI19_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI20_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI20_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI21_22_29_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI21_22_29_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI30_32_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI30_32_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI33_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI33_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_BRK_TIM15_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_BRK_TIM15_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_UP_TIM16_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_UP_TIM16_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY" -#endif - -#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_CC_PRIORITY) -#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_CC_PRIORITY" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/stm32_isr.h + * @brief STM32F3xx ISR handler header. + * + * @addtogroup STM32F3xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 + +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 + +#define STM32_I2C3_EVENT_HANDLER Vector160 +#define STM32_I2C3_ERROR_HANDLER Vector164 +#define STM32_I2C3_EVENT_NUMBER 72 +#define STM32_I2C3_ERROR_NUMBER 73 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER VectorA4 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_CC_HANDLER VectorF8 +#define STM32_TIM15_HANDLER VectorA0 /* Note: same as STM32_TIM1_BRK */ +#define STM32_TIM16_HANDLER VectorA4 /* Note: same as STM32_TIM1_UP */ +#define STM32_TIM17_HANDLER VectorA8 /* Note: same as STM32_TIM1_TRG_COM */ +#define STM32_TIM20_UP_HANDLER Vector178 +#define STM32_TIM20_CC_HANDLER Vector180 + +#define STM32_TIM1_UP_NUMBER 25 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_CC_NUMBER 46 +#define STM32_TIM15_NUMBER 24 /* Note: same as STM32_TIM1_BRK */ +#define STM32_TIM16_NUMBER 25 /* Note: same as STM32_TIM1_UP */ +#define STM32_TIM17_NUMBER 26 /* Note: same as STM32_TIM1_TRG_COM */ +#define STM32_TIM20_UP_NUMBER 78 +#define STM32_TIM20_CC_NUMBER 80 + +/* + * HRTIM units (F334) + */ +#define STM32_HRTIM_MASTER_HANDLER Vector14C +#define STM32_HRTIM_TIMA_HANDLER Vector150 +#define STM32_HRTIM_TIMB_HANDLER Vector154 +#define STM32_HRTIM_TIMC_HANDLER Vector158 +#define STM32_HRTIM_TIMD_HANDLER Vector15C +#define STM32_HRTIM_TIME_HANDLER Vector160 +#define STM32_HRTIM_FLT_HANDLER Vector164 + +#define STM32_HRTIM_MASTER_NUMBER 67 +#define STM32_HRTIM_TIMA_NUMBER 68 +#define STM32_HRTIM_TIMB_NUMBER 69 +#define STM32_HRTIM_TIMC_NUMBER 70 +#define STM32_HRTIM_TIMD_NUMBER 71 +#define STM32_HRTIM_TIME_NUMBER 72 +#define STM32_HRTIM_FLT_NUMBER 73 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 + +/* + * USB units. + */ +#define STM32_USB1_HP_HANDLER Vector168 +#define STM32_USB1_LP_HANDLER Vector16C + +#define STM32_USB1_HP_NUMBER 74 +#define STM32_USB1_LP_NUMBER 75 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI0_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI1_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI2_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI3_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI4_PRIORITY 6 +#endif + +/** + * @brief EXTI5..9 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#endif + +/** + * @brief EXTI10..15 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI16_PRIORITY 6 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI17_PRIORITY 6 +#endif + +/** + * @brief EXTI18 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI18_PRIORITY 6 +#endif + +/** + * @brief EXTI19 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI19_PRIORITY 6 +#endif + +/** + * @brief EXTI20 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI20_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI20_PRIORITY 6 +#endif + +/** + * @brief EXTI21,22,29 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI21_22_29_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 +#endif + +/** + * @brief EXTI30..32 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI30_32_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI30_32_PRIORITY 6 +#endif + +/** + * @brief EXTI33 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI33_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI33_PRIORITY 6 +#endif + +/** + * @brief TIM1-BRK, TIM15 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_TIM1_BRK_TIM15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#endif + +/** + * @brief TIM1-UP, TIM16 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_TIM1_UP_TIM16_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#endif + +/** + * @brief TIM1-TRG-COM, TIM17 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#endif + +/** + * @brief TIM1-CC interrupt priority level setting. + */ +#if !defined(STM32_IRQ_TIM1_CC_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_TIM1_CC_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* IRQ priority checks.*/ +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI0_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI0_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI1_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI1_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI2_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI2_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI3_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI3_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI4_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI4_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI5_9_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI5_9_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI10_15_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI10_15_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI16_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI16_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI17_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI17_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI18_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI18_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI19_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI19_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI20_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI20_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI21_22_29_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI21_22_29_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI30_32_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI30_32_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI33_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI33_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_BRK_TIM15_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_BRK_TIM15_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_UP_TIM16_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_UP_TIM16_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY" +#endif + +#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_CC_PRIORITY) +#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_CC_PRIORITY" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F3xx/stm32_rcc.h b/os/hal/ports/STM32/STM32F3xx/stm32_rcc.h index 4db714d80a..04631cc663 100644 --- a/os/hal/ports/STM32/STM32F3xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32F3xx/stm32_rcc.h @@ -1,1026 +1,1026 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f30x.h. - * - * @addtogroup STM32F3xx_RCC - * @{ - */ - -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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); \ - (void)RCC->APB1ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - (void)RCC->APB1ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @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); \ - (void)RCC->APB2ENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - (void)RCC->APB2ENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - (void)RCC->AHBENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#if defined(RCC_AHBENR_ADC12EN) || defined(__DOXYGEN__) -#define rccEnableADC12(lp) rccEnableAHB(RCC_AHBENR_ADC12EN, lp) -#else -#define rccEnableADC12(lp) rccEnableAHB(RCC_AHBENR_ADC1EN, lp) -#endif - -/** - * @brief Disables the ADC1/ADC2 peripheral clock. - * - * @api - */ -#if defined(RCC_AHBENR_ADC12EN) || defined(__DOXYGEN__) -#define rccDisableADC12() rccDisableAHB(RCC_AHBENR_ADC12EN) -#else -#define rccDisableADC12() rccDisableAHB(RCC_AHBENR_ADC1EN) -#endif - -/** - * @brief Resets the ADC1/ADC2 peripheral. - * - * @api - */ -#if defined(RCC_AHBRSTR_ADC12RST) || defined(__DOXYGEN__) -#define rccResetADC12() rccResetAHB(RCC_AHBRSTR_ADC12RST) -#else -#define rccResetADC12() rccResetAHB(RCC_AHBRSTR_ADC1RST) -#endif - -/** - * @brief Enables the ADC3/ADC4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#if defined(RCC_AHBENR_ADC34EN) || defined(__DOXYGEN__) -#define rccEnableADC34(lp) rccEnableAHB(RCC_AHBENR_ADC34EN, lp) -#else -#define rccEnableADC34(lp) rccEnableAHB(RCC_AHBENR_ADC3EN, lp) -#endif - -/** - * @brief Disables the ADC3/ADC4 peripheral clock. - * - * @api - */ -#if defined(RCC_AHBENR_ADC34EN) || defined(__DOXYGEN__) -#define rccDisableADC34() rccDisableAHB(RCC_AHBENR_ADC34EN) -#else -#define rccDisableADC34() rccDisableAHB(RCC_AHBENR_ADC3EN) -#endif - -/** - * @brief Resets the ADC3/ADC4 peripheral. - * - * @api - */ -#if defined(RCC_AHBRSTR_ADC34RST) || defined(__DOXYGEN__) -#define rccResetADC34() rccResetAHB(RCC_AHBRSTR_ADC34RST) -#else -#define rccResetADC34() rccResetAHB(RCC_AHBRSTR_ADC3RST) -#endif -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DAC1RST) - -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC2(lp) rccEnableAPB1(RCC_APB1ENR_DAC2EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC2() rccDisableAPB1(RCC_APB1ENR_DAC2EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC2() rccResetAPB1(RCC_APB1RSTR_DAC2RST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CANEN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CANEN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CANRST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) - -/** - * @brief Enables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) - -/** - * @brief Enables the TIM20 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM20(lp) rccEnableAPB2(RCC_APB2ENR_TIM20EN, lp) - -/** - * @brief Disables the TIM20 peripheral clock. - * - * @api - */ -#define rccDisableTIM20(lp) rccDisableAPB2(RCC_APB2ENR_TIM20EN) - -/** - * @brief Resets the TIM20 peripheral. - * - * @api - */ -#define rccResetTIM20() rccResetAPB2(RCC_APB2RSTR_TIM20RST) -/** @} */ - -/** - * @name HRTIM peripheral specific RCC operations - * @{ - */ -/** - - * @brief Enables the HRTIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableHRTIM1(lp) rccEnableAPB2(RCC_APB2ENR_HRTIM1EN, lp) - -/** - * @brief Disables the HRTIM1 peripheral clock. - * - * @api - */ -#define rccDisableHRTIM1(lp) rccDisableAPB2(RCC_APB2ENR_HRTIM1EN) - -/** - * @brief Resets the HRTIM1 peripheral. - * - * @api - - */ -#define rccResetHRTIM1() rccResetAPB2(RCC_APB2RSTR_HRTIM1RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @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. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFSMC(lp) rccEnableAHB(RCC_AHBENR_FMCEN, lp) - -/** - * @brief Disables the FMC peripheral clock. - * - * @api - */ -#define rccDisableFSMC() rccDisableAHB(RCC_AHBENR_FMCEN) -/** @} */ - -/** - * @name CRC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f30x.h. + * + * @addtogroup STM32F3xx_RCC + * @{ + */ + +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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); \ + (void)RCC->APB1ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + (void)RCC->APB1ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @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); \ + (void)RCC->APB2ENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + (void)RCC->APB2ENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + (void)RCC->AHBENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#if defined(RCC_AHBENR_ADC12EN) || defined(__DOXYGEN__) +#define rccEnableADC12(lp) rccEnableAHB(RCC_AHBENR_ADC12EN, lp) +#else +#define rccEnableADC12(lp) rccEnableAHB(RCC_AHBENR_ADC1EN, lp) +#endif + +/** + * @brief Disables the ADC1/ADC2 peripheral clock. + * + * @api + */ +#if defined(RCC_AHBENR_ADC12EN) || defined(__DOXYGEN__) +#define rccDisableADC12() rccDisableAHB(RCC_AHBENR_ADC12EN) +#else +#define rccDisableADC12() rccDisableAHB(RCC_AHBENR_ADC1EN) +#endif + +/** + * @brief Resets the ADC1/ADC2 peripheral. + * + * @api + */ +#if defined(RCC_AHBRSTR_ADC12RST) || defined(__DOXYGEN__) +#define rccResetADC12() rccResetAHB(RCC_AHBRSTR_ADC12RST) +#else +#define rccResetADC12() rccResetAHB(RCC_AHBRSTR_ADC1RST) +#endif + +/** + * @brief Enables the ADC3/ADC4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#if defined(RCC_AHBENR_ADC34EN) || defined(__DOXYGEN__) +#define rccEnableADC34(lp) rccEnableAHB(RCC_AHBENR_ADC34EN, lp) +#else +#define rccEnableADC34(lp) rccEnableAHB(RCC_AHBENR_ADC3EN, lp) +#endif + +/** + * @brief Disables the ADC3/ADC4 peripheral clock. + * + * @api + */ +#if defined(RCC_AHBENR_ADC34EN) || defined(__DOXYGEN__) +#define rccDisableADC34() rccDisableAHB(RCC_AHBENR_ADC34EN) +#else +#define rccDisableADC34() rccDisableAHB(RCC_AHBENR_ADC3EN) +#endif + +/** + * @brief Resets the ADC3/ADC4 peripheral. + * + * @api + */ +#if defined(RCC_AHBRSTR_ADC34RST) || defined(__DOXYGEN__) +#define rccResetADC34() rccResetAHB(RCC_AHBRSTR_ADC34RST) +#else +#define rccResetADC34() rccResetAHB(RCC_AHBRSTR_ADC3RST) +#endif +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DAC1RST) + +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC2(lp) rccEnableAPB1(RCC_APB1ENR_DAC2EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC2() rccDisableAPB1(RCC_APB1ENR_DAC2EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC2() rccResetAPB1(RCC_APB1RSTR_DAC2RST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CANEN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CANEN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CANRST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) + +/** + * @brief Enables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) + +/** + * @brief Enables the TIM20 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM20(lp) rccEnableAPB2(RCC_APB2ENR_TIM20EN, lp) + +/** + * @brief Disables the TIM20 peripheral clock. + * + * @api + */ +#define rccDisableTIM20(lp) rccDisableAPB2(RCC_APB2ENR_TIM20EN) + +/** + * @brief Resets the TIM20 peripheral. + * + * @api + */ +#define rccResetTIM20() rccResetAPB2(RCC_APB2RSTR_TIM20RST) +/** @} */ + +/** + * @name HRTIM peripheral specific RCC operations + * @{ + */ +/** + + * @brief Enables the HRTIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableHRTIM1(lp) rccEnableAPB2(RCC_APB2ENR_HRTIM1EN, lp) + +/** + * @brief Disables the HRTIM1 peripheral clock. + * + * @api + */ +#define rccDisableHRTIM1(lp) rccDisableAPB2(RCC_APB2ENR_HRTIM1EN) + +/** + * @brief Resets the HRTIM1 peripheral. + * + * @api + + */ +#define rccResetHRTIM1() rccResetAPB2(RCC_APB2RSTR_HRTIM1RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @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. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFSMC(lp) rccEnableAHB(RCC_AHBENR_FMCEN, lp) + +/** + * @brief Disables the FMC peripheral clock. + * + * @api + */ +#define rccDisableFSMC() rccDisableAHB(RCC_AHBENR_FMCEN) +/** @} */ + +/** + * @name CRC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F3xx/stm32_registry.h b/os/hal/ports/STM32/STM32F3xx/stm32_registry.h index e75cf52887..1edbec9866 100644 --- a/os/hal/ports/STM32/STM32F3xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32F3xx/stm32_registry.h @@ -1,3130 +1,3130 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F3xx/stm32_registry.h - * @brief STM32F3xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32F3XX) || defined(__DOXYGEN__) -#define STM32F3XX -#endif - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F3xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/*===========================================================================*/ -/* STM32F303xC. */ -/*===========================================================================*/ -#if defined(STM32F303xC) || defined(__DOXYGEN__) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_HANDLER VectorFC -#define STM32_ADC3_NUMBER 47 -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_ADC3_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC4 TRUE -#define STM32_ADC4_HANDLER Vector134 -#define STM32_ADC4_NUMBER 61 -#define STM32_ADC4_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC4_DMA_CHN 0x00000000 - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN) -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F303xC) */ - -/*===========================================================================*/ -/* STM32F303xE. */ -/*===========================================================================*/ -#if defined(STM32F303xE) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_HANDLER VectorFC -#define STM32_ADC3_NUMBER 47 -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_ADC3_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC4 TRUE -#define STM32_ADC4_HANDLER Vector134 -#define STM32_ADC4_NUMBER 61 -#define STM32_ADC4_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC4_DMA_CHN 0x00000000 - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN | \ - RCC_AHBENR_GPIOGEN | \ - RCC_AHBENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM20 TRUE -#define STM32_TIM20_IS_32BITS FALSE -#define STM32_TIM20_CHANNELS 6 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F303xE) */ - -/*===========================================================================*/ -/* STM32F303x8. */ -/*===========================================================================*/ -#if defined(STM32F303x8) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F303x8) */ - -/*===========================================================================*/ -/* STM32F301x8. */ -/*===========================================================================*/ -#if defined(STM32F301x8) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI1 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F301x8) */ - -/*===========================================================================*/ -/* STM32F302x8. */ -/*===========================================================================*/ -#if defined(STM32F302x8) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI1 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F302x8) */ - -/*===========================================================================*/ -/* STM32F302xC. */ -/*===========================================================================*/ -#if defined(STM32F302xC) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F302xC) */ - -/*===========================================================================*/ -/* STM32F302xE. */ -/*===========================================================================*/ -#if defined(STM32F302xE) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN | \ - RCC_AHBENR_GPIOGEN | \ - RCC_AHBENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 768 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F302xE) */ - -/*===========================================================================*/ -/* STM32F318x8. */ -/*===========================================================================*/ -#if defined(STM32F318x8) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI1 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F318x8) */ - -/*===========================================================================*/ -/* STM32F328x8. */ -/*===========================================================================*/ -#if defined(STM32F328x8) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F328x8) */ - -/*===========================================================================*/ -/* STM32F358xC. */ -/*===========================================================================*/ -#if defined(STM32F358xC) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F358xC) */ - -/*===========================================================================*/ -/* STM32F334x8. */ -/*===========================================================================*/ -#if defined(STM32F334x8) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 1 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* HRTIM attributes.*/ -#define STM32_HAS_HRTIM1 TRUE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F334x8) */ - -/*===========================================================================*/ -/* STM32F398xx. */ -/*===========================================================================*/ -#if defined(STM32F398xx) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_HANDLER VectorFC -#define STM32_ADC3_NUMBER 47 -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_ADC3_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC4 TRUE -#define STM32_ADC4_HANDLER Vector134 -#define STM32_ADC4_NUMBER 61 -#define STM32_ADC4_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC4_DMA_CHN 0x00000000 - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN | \ - RCC_AHBENR_GPIOGEN | \ - RCC_AHBENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 64 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM20 TRUE -#define STM32_TIM20_IS_32BITS FALSE -#define STM32_TIM20_CHANNELS 6 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE -#endif /* defined(STM32F398xx) */ - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F3xx/stm32_registry.h + * @brief STM32F3xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32F3XX) || defined(__DOXYGEN__) +#define STM32F3XX +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F3xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/*===========================================================================*/ +/* STM32F303xC. */ +/*===========================================================================*/ +#if defined(STM32F303xC) || defined(__DOXYGEN__) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_HANDLER VectorFC +#define STM32_ADC3_NUMBER 47 +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_ADC3_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC4 TRUE +#define STM32_ADC4_HANDLER Vector134 +#define STM32_ADC4_NUMBER 61 +#define STM32_ADC4_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC4_DMA_CHN 0x00000000 + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN) +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F303xC) */ + +/*===========================================================================*/ +/* STM32F303xE. */ +/*===========================================================================*/ +#if defined(STM32F303xE) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_HANDLER VectorFC +#define STM32_ADC3_NUMBER 47 +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_ADC3_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC4 TRUE +#define STM32_ADC4_HANDLER Vector134 +#define STM32_ADC4_NUMBER 61 +#define STM32_ADC4_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC4_DMA_CHN 0x00000000 + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN | \ + RCC_AHBENR_GPIOGEN | \ + RCC_AHBENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM20 TRUE +#define STM32_TIM20_IS_32BITS FALSE +#define STM32_TIM20_CHANNELS 6 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F303xE) */ + +/*===========================================================================*/ +/* STM32F303x8. */ +/*===========================================================================*/ +#if defined(STM32F303x8) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F303x8) */ + +/*===========================================================================*/ +/* STM32F301x8. */ +/*===========================================================================*/ +#if defined(STM32F301x8) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI1 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F301x8) */ + +/*===========================================================================*/ +/* STM32F302x8. */ +/*===========================================================================*/ +#if defined(STM32F302x8) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI1 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F302x8) */ + +/*===========================================================================*/ +/* STM32F302xC. */ +/*===========================================================================*/ +#if defined(STM32F302xC) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F302xC) */ + +/*===========================================================================*/ +/* STM32F302xE. */ +/*===========================================================================*/ +#if defined(STM32F302xE) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN | \ + RCC_AHBENR_GPIOGEN | \ + RCC_AHBENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 768 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F302xE) */ + +/*===========================================================================*/ +/* STM32F318x8. */ +/*===========================================================================*/ +#if defined(STM32F318x8) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI1 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F318x8) */ + +/*===========================================================================*/ +/* STM32F328x8. */ +/*===========================================================================*/ +#if defined(STM32F328x8) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F328x8) */ + +/*===========================================================================*/ +/* STM32F358xC. */ +/*===========================================================================*/ +#if defined(STM32F358xC) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F358xC) */ + +/*===========================================================================*/ +/* STM32F334x8. */ +/*===========================================================================*/ +#if defined(STM32F334x8) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 1 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* HRTIM attributes.*/ +#define STM32_HAS_HRTIM1 TRUE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F334x8) */ + +/*===========================================================================*/ +/* STM32F398xx. */ +/*===========================================================================*/ +#if defined(STM32F398xx) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_HANDLER VectorFC +#define STM32_ADC3_NUMBER 47 +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_ADC3_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC4 TRUE +#define STM32_ADC4_HANDLER Vector134 +#define STM32_ADC4_NUMBER 61 +#define STM32_ADC4_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC4_DMA_CHN 0x00000000 + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN | \ + RCC_AHBENR_GPIOGEN | \ + RCC_AHBENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 64 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM20 TRUE +#define STM32_TIM20_IS_32BITS FALSE +#define STM32_TIM20_CHANNELS 6 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE +#endif /* defined(STM32F398xx) */ + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld.c b/os/hal/ports/STM32/STM32F4xx/hal_lld.c index b2b8a11978..aa51a7ac14 100644 --- a/os/hal/ports/STM32/STM32F4xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32F4xx/hal_lld.c @@ -1,341 +1,342 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/hal_lld.c - * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f4xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - -#if STM32_BKPRAM_ENABLE - rccEnableBKPSRAM(true); - - PWR->CSR |= PWR_CSR_BRE; - while ((PWR->CSR & PWR_CSR_BRR) == 0) - ; /* Waits until the regulator is stable */ -#else - PWR->CSR &= ~PWR_CSR_BRE; -#endif /* STM32_BKPRAM_ENABLE */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. AHB3 is not reseted because it could have - been initialized in the board initialization file (board.c). - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB1(~STM32_GPIO_EN_MASK); -#if !defined(STM32F410xx) - rccResetAHB2(~0); -#endif - rccResetAPB1(~RCC_APB1RSTR_PWRRST); - rccResetAPB2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32F2xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ -#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR_RTCAPBEN) - RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_RTCAPBEN; -#else - RCC->APB1ENR = RCC_APB1ENR_PWREN; -#endif - - /* PWR initialization.*/ -#if defined(STM32F4XX) || defined(__DOXYGEN__) - PWR->CR = STM32_VOS; -#else - PWR->CR = 0; -#endif - - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. Clearing the register has to be postponed after HSI is the - new source.*/ - RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers finally cleared to reset values.*/ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN | - STM32_PLLM; - RCC->CR |= RCC_CR_PLLON; - - /* Synchronization with voltage regulator stabilization.*/ -#if defined(STM32F4XX) - while ((PWR->CSR & PWR_CSR_VOSRDY) == 0) - ; /* Waits until power regulator is stable. */ - -#if STM32_OVERDRIVE_REQUIRED - /* Overdrive activation performed after activating the PLL in order to save - time as recommended in RM in "Entering Over-drive mode" paragraph.*/ - PWR->CR |= PWR_CR_ODEN; - while (!(PWR->CSR & PWR_CSR_ODRDY)) - ; - PWR->CR |= PWR_CR_ODSWEN; - while (!(PWR->CSR & PWR_CSR_ODSWRDY)) - ; -#endif /* STM32_OVERDRIVE_REQUIRED */ -#endif /* defined(STM32F4XX) */ - - /* Waiting for PLL lock.*/ - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; -#endif /* STM32_ACTIVATE_PLL */ - -#if STM32_ACTIVATE_PLLI2S - /* PLLI2S activation.*/ - RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SN | STM32_PLLI2SP | - STM32_PLLI2SSRC | STM32_PLLI2SQ | STM32_PLLI2SM; - RCC->CR |= RCC_CR_PLLI2SON; - - /* Waiting for PLL lock.*/ - while (!(RCC->CR & RCC_CR_PLLI2SRDY)) - ; -#endif /* STM32_ACTIVATE_PLLI2S */ - -#if STM32_ACTIVATE_PLLSAI - /* PLLSAI activation.*/ - RCC->PLLSAICFGR = STM32_PLLSAIR | STM32_PLLSAIN | STM32_PLLSAIP | - STM32_PLLSAIQ | STM32_PLLSAIM; - RCC->CR |= RCC_CR_PLLSAION; - - /* Waiting for PLL lock.*/ - while (!(RCC->CR & RCC_CR_PLLSAIRDY)) - ; -#endif /* STM32_ACTIVATE_PLLSAI */ - - /* Other clock-related settings (dividers, MCO etc).*/ -#if !defined(STM32F413xx) - RCC->CFGR = STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | - STM32_I2SSRC | STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | - STM32_HPRE; -#else - RCC->CFGR = STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | - STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | - STM32_HPRE; -#endif - -#if STM32_HAS_RCC_DCKCFGR - /* DCKCFGR register initialization, note, must take care of the _OFF - pseudo settings.*/ - { - uint32_t dckcfgr = 0; -#if STM32_SAI2SEL != STM32_SAI2SEL_OFF - dckcfgr |= STM32_SAI2SEL; -#endif -#if STM32_SAI1SEL != STM32_SAI1SEL_OFF - dckcfgr |= STM32_SAI1SEL; -#endif -#if (STM32_ACTIVATE_PLLSAI == TRUE) && \ - (STM32_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF) - dckcfgr |= STM32_PLLSAIDIVR; -#endif -#if defined(STM32F469xx) || defined(STM32F479xx) - /* Special case, in those devices STM32_CK48MSEL is located in the - DCKCFGR register.*/ - dckcfgr |= STM32_CK48MSEL; -#endif -#if !defined(STM32F413xx) - RCC->DCKCFGR = dckcfgr | - STM32_TIMPRE | STM32_PLLSAIDIVQ | STM32_PLLI2SDIVQ; -#else - RCC->DCKCFGR = dckcfgr | - STM32_TIMPRE | STM32_PLLDIVR | STM32_PLLI2SDIVR; -#endif - } -#endif - -#if STM32_HAS_RCC_DCKCFGR2 - /* DCKCFGR2 register initialization.*/ - RCC->DCKCFGR2 = STM32_CK48MSEL; -#endif - - /* Flash setup.*/ -#if !defined(STM32_REMOVE_REVISION_A_FIX) - /* Some old revisions of F4x MCUs randomly crashes with compiler - optimizations enabled AND flash caches enabled. */ - if ((DBGMCU->IDCODE == 0x20006411) && (SCB->CPUID == 0x410FC241)) - FLASH->ACR = FLASH_ACR_PRFTEN | STM32_FLASHBITS; - else - FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | - FLASH_ACR_DCEN | STM32_FLASHBITS; -#else - FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | - FLASH_ACR_DCEN | STM32_FLASHBITS; -#endif - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif -#endif /* STM32_NO_INIT */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/hal_lld.c + * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f4xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + +#if STM32_BKPRAM_ENABLE + rccEnableBKPSRAM(true); + + PWR->CSR |= PWR_CSR_BRE; + while ((PWR->CSR & PWR_CSR_BRR) == 0) + ; /* Waits until the regulator is stable */ +#else + PWR->CSR &= ~PWR_CSR_BRE; +#endif /* STM32_BKPRAM_ENABLE */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. AHB3 is not reseted because it could have + been initialized in the board initialization file (board.c). + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~STM32_GPIO_EN_MASK); +#if !defined(STM32F410xx) + rccResetAHB2(~0); +#endif + rccResetAPB1(~RCC_APB1RSTR_PWRRST); + rccResetAPB2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32F2xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ +#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR_RTCAPBEN) + RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_RTCAPBEN; +#else + RCC->APB1ENR = RCC_APB1ENR_PWREN; +#endif + + /* PWR initialization.*/ +#if defined(STM32F4XX) || defined(__DOXYGEN__) + PWR->CR = STM32_VOS; +#else + PWR->CR = 0; +#endif + + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. Clearing the register has to be postponed after HSI is the + new source.*/ + RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers finally cleared to reset values.*/ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN | + STM32_PLLM; + RCC->CR |= RCC_CR_PLLON; + + /* Synchronization with voltage regulator stabilization.*/ +#if defined(STM32F4XX) + while ((PWR->CSR & PWR_CSR_VOSRDY) == 0) + ; /* Waits until power regulator is stable. */ + +#if STM32_OVERDRIVE_REQUIRED + /* Overdrive activation performed after activating the PLL in order to save + time as recommended in RM in "Entering Over-drive mode" paragraph.*/ + PWR->CR |= PWR_CR_ODEN; + while (!(PWR->CSR & PWR_CSR_ODRDY)) + ; + PWR->CR |= PWR_CR_ODSWEN; + while (!(PWR->CSR & PWR_CSR_ODSWRDY)) + ; +#endif /* STM32_OVERDRIVE_REQUIRED */ +#endif /* defined(STM32F4XX) */ + + /* Waiting for PLL lock.*/ + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; +#endif /* STM32_ACTIVATE_PLL */ + +#if STM32_ACTIVATE_PLLI2S + /* PLLI2S activation.*/ + RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SN | STM32_PLLI2SP | + STM32_PLLI2SSRC | STM32_PLLI2SQ | STM32_PLLI2SM; + RCC->CR |= RCC_CR_PLLI2SON; + + /* Waiting for PLL lock.*/ + while (!(RCC->CR & RCC_CR_PLLI2SRDY)) + ; +#endif /* STM32_ACTIVATE_PLLI2S */ + +#if STM32_ACTIVATE_PLLSAI + /* PLLSAI activation.*/ + RCC->PLLSAICFGR = STM32_PLLSAIR | STM32_PLLSAIN | STM32_PLLSAIP | + STM32_PLLSAIQ | STM32_PLLSAIM; + RCC->CR |= RCC_CR_PLLSAION; + + /* Waiting for PLL lock.*/ + while (!(RCC->CR & RCC_CR_PLLSAIRDY)) + ; +#endif /* STM32_ACTIVATE_PLLSAI */ + + /* Other clock-related settings (dividers, MCO etc).*/ +#if !defined(STM32F413xx) + RCC->CFGR = STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | + STM32_I2SSRC | STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE; +#else + RCC->CFGR = STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | + STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE; +#endif + +#if STM32_HAS_RCC_DCKCFGR + /* DCKCFGR register initialization, note, must take care of the _OFF + pseudo settings.*/ + { + uint32_t dckcfgr = 0; +#if STM32_SAI2SEL != STM32_SAI2SEL_OFF + dckcfgr |= STM32_SAI2SEL; +#endif +#if STM32_SAI1SEL != STM32_SAI1SEL_OFF + dckcfgr |= STM32_SAI1SEL; +#endif +#if (STM32_ACTIVATE_PLLSAI == TRUE) && \ + (STM32_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF) + dckcfgr |= STM32_PLLSAIDIVR; +#endif +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Special case, in those devices STM32_CK48MSEL is located in the + DCKCFGR register.*/ + dckcfgr |= STM32_CK48MSEL; +#endif +#if !defined(STM32F413xx) + RCC->DCKCFGR = dckcfgr | + STM32_TIMPRE | STM32_PLLSAIDIVQ | STM32_PLLI2SDIVQ; +#else + RCC->DCKCFGR = dckcfgr | + STM32_TIMPRE | STM32_PLLDIVR | STM32_PLLI2SDIVR; +#endif + } +#endif + +#if STM32_HAS_RCC_DCKCFGR2 + /* DCKCFGR2 register initialization.*/ + RCC->DCKCFGR2 = STM32_CK48MSEL; +#endif + + /* Flash setup.*/ +#if !defined(STM32_REMOVE_REVISION_A_FIX) + /* Some old revisions of F4x MCUs randomly crashes with compiler + optimizations enabled AND flash caches enabled. */ + if ((DBGMCU->IDCODE == 0x20006411) && (SCB->CPUID == 0x410FC241)) + FLASH->ACR = FLASH_ACR_PRFTEN | STM32_FLASHBITS; + else + FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | + FLASH_ACR_DCEN | STM32_FLASHBITS; +#else + FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | + FLASH_ACR_DCEN | STM32_FLASHBITS; +#endif + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld.h b/os/hal/ports/STM32/STM32F4xx/hal_lld.h index 1063dc09fb..68501510ca 100644 --- a/os/hal/ports/STM32/STM32F4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32F4xx/hal_lld.h @@ -1,278 +1,278 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/hal_lld.h - * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -#if defined(STM32F413xx) -#include "hal_lld_type2.h" -#else -#include "hal_lld_type1.h" -#endif - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** - * @brief MCO1 divider clock. - */ -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__) -#define STM32_MCO1DIVCLK STM32_HSICLK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE -#define STM32_MCO1DIVCLK STM32_LSECLK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE -#define STM32_MCO1DIVCLK STM32_HSECLK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL -#define STM32_MCO1DIVCLK STM32_PLLCLKOUT - -#else -#error "invalid STM32_MCO1SEL value specified" -#endif - -/** - * @brief MCO1 output pin clock. - */ -#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCO1CLK STM32_MCO1DIVCLK - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2) - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3) - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4) - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5) - -#else -#error "invalid STM32_MCO1PRE value specified" -#endif - -/** - * @brief MCO2 divider clock. - */ -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__) -#define STM32_MCO2DIVCLK STM32_HSECLK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL -#define STM32_MCO2DIVCLK STM32_PLLCLKOUT - -#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK -#define STM32_MCO2DIVCLK STM32_SYSCLK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S -#define STM32_MCO2DIVCLK STM32_PLLI2S - -#else -#error "invalid STM32_MCO2SEL value specified" -#endif - -/** - * @brief MCO2 output pin clock. - */ -#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCO2CLK STM32_MCO2DIVCLK - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2) - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3) - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4) - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5) - -#else -#error "invalid STM32_MCO2PRE value specified" -#endif - -/** - * @brief RTC HSE divider setting. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief HSE divider toward RTC clock. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK STM32_HSEDIVCLK - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief 48MHz frequency. - */ -#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) -#if STM32_HAS_RCC_CK48MSEL || defined(__DOXYGEN__) -#if (STM32_CK48MSEL == STM32_CK48MSEL_PLL) || defined(__DOXYGEN__) -#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) -#elif STM32_CK48MSEL == STM32_CK48MSEL_PLLALT -#define STM32_PLL48CLK STM32_PLL48CLK_ALTSRC -#else -#error "invalid source selected for PLL48CLK clock" -#endif -#else /* !STM32_HAS_RCC_CK48MSEL */ -#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) -#endif /* !STM32_HAS_RCC_CK48MSEL */ -#else /* !STM32_CLOCK48_REQUIRED */ -#define STM32_PLL48CLK 0 -#endif /* STM32_CLOCK48_REQUIRED */ - -#if !STM32_HAS_RCC_DCKCFGR || (STM32_TIMPRE == STM32_TIMPRE_PCLK) || \ - defined(__DOXYGEN__) -/** - * @brief Clock of timers connected to APB1 - * (Timers 2, 3, 4, 5, 6, 7, 12, 13, 14). - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Clock of timers connected to APB2 (Timers 1, 8, 9, 10, 11). - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -#else /* STM32_HAS_RCC_DCKCFGR && (STM32_TIMPRE == STM32_TIMPRE_HCLK) */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || \ - (STM32_PPRE1 == STM32_PPRE1_DIV2) || \ - ((STM32_PPRE1 == STM32_PPRE1_DIV4) && \ - (STM32_TIMPRE_PRESCALE4 == TRUE)) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 STM32_HCLK -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 4) -#endif - -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || \ - (STM32_PPRE2 == STM32_PPRE2_DIV2) || \ - ((STM32_PPRE2 == STM32_PPRE2_DIV4) && \ - (STM32_TIMPRE_PRESCALE4 == TRUE)) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 STM32_HCLK -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 4) -#endif -#endif /* STM32_HAS_RCC_DCKCFGR && (STM32_TIMPRE == STM32_TIMPRE_HCLK) */ - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000000 -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS 0x00000001 -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS 0x00000002 -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS 0x00000003 -#elif STM32_HCLK <= STM32_4WS_THRESHOLD -#define STM32_FLASHBITS 0x00000004 -#elif STM32_HCLK <= STM32_5WS_THRESHOLD -#define STM32_FLASHBITS 0x00000005 -#elif STM32_HCLK <= STM32_6WS_THRESHOLD -#define STM32_FLASHBITS 0x00000006 -#elif STM32_HCLK <= STM32_7WS_THRESHOLD -#define STM32_FLASHBITS 0x00000007 -#elif STM32_HCLK <= STM32_8WS_THRESHOLD -#define STM32_FLASHBITS 0x00000008 -#else -#error "invalid frequency at specified VDD level" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/hal_lld.h + * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +#if defined(STM32F413xx) +#include "hal_lld_type2.h" +#else +#include "hal_lld_type1.h" +#endif + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @brief MCO1 divider clock. + */ +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__) +#define STM32_MCO1DIVCLK STM32_HSICLK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE +#define STM32_MCO1DIVCLK STM32_LSECLK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE +#define STM32_MCO1DIVCLK STM32_HSECLK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL +#define STM32_MCO1DIVCLK STM32_PLLCLKOUT + +#else +#error "invalid STM32_MCO1SEL value specified" +#endif + +/** + * @brief MCO1 output pin clock. + */ +#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCO1CLK STM32_MCO1DIVCLK + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2) + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3) + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4) + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5) + +#else +#error "invalid STM32_MCO1PRE value specified" +#endif + +/** + * @brief MCO2 divider clock. + */ +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__) +#define STM32_MCO2DIVCLK STM32_HSECLK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL +#define STM32_MCO2DIVCLK STM32_PLLCLKOUT + +#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK +#define STM32_MCO2DIVCLK STM32_SYSCLK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S +#define STM32_MCO2DIVCLK STM32_PLLI2S + +#else +#error "invalid STM32_MCO2SEL value specified" +#endif + +/** + * @brief MCO2 output pin clock. + */ +#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCO2CLK STM32_MCO2DIVCLK + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2) + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3) + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4) + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5) + +#else +#error "invalid STM32_MCO2PRE value specified" +#endif + +/** + * @brief RTC HSE divider setting. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief HSE divider toward RTC clock. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK STM32_HSEDIVCLK + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief 48MHz frequency. + */ +#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) +#if STM32_HAS_RCC_CK48MSEL || defined(__DOXYGEN__) +#if (STM32_CK48MSEL == STM32_CK48MSEL_PLL) || defined(__DOXYGEN__) +#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) +#elif STM32_CK48MSEL == STM32_CK48MSEL_PLLALT +#define STM32_PLL48CLK STM32_PLL48CLK_ALTSRC +#else +#error "invalid source selected for PLL48CLK clock" +#endif +#else /* !STM32_HAS_RCC_CK48MSEL */ +#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) +#endif /* !STM32_HAS_RCC_CK48MSEL */ +#else /* !STM32_CLOCK48_REQUIRED */ +#define STM32_PLL48CLK 0 +#endif /* STM32_CLOCK48_REQUIRED */ + +#if !STM32_HAS_RCC_DCKCFGR || (STM32_TIMPRE == STM32_TIMPRE_PCLK) || \ + defined(__DOXYGEN__) +/** + * @brief Clock of timers connected to APB1 + * (Timers 2, 3, 4, 5, 6, 7, 12, 13, 14). + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Clock of timers connected to APB2 (Timers 1, 8, 9, 10, 11). + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +#else /* STM32_HAS_RCC_DCKCFGR && (STM32_TIMPRE == STM32_TIMPRE_HCLK) */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || \ + (STM32_PPRE1 == STM32_PPRE1_DIV2) || \ + ((STM32_PPRE1 == STM32_PPRE1_DIV4) && \ + (STM32_TIMPRE_PRESCALE4 == TRUE)) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 STM32_HCLK +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 4) +#endif + +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || \ + (STM32_PPRE2 == STM32_PPRE2_DIV2) || \ + ((STM32_PPRE2 == STM32_PPRE2_DIV4) && \ + (STM32_TIMPRE_PRESCALE4 == TRUE)) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 STM32_HCLK +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 4) +#endif +#endif /* STM32_HAS_RCC_DCKCFGR && (STM32_TIMPRE == STM32_TIMPRE_HCLK) */ + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000000 +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS 0x00000001 +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS 0x00000002 +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS 0x00000003 +#elif STM32_HCLK <= STM32_4WS_THRESHOLD +#define STM32_FLASHBITS 0x00000004 +#elif STM32_HCLK <= STM32_5WS_THRESHOLD +#define STM32_FLASHBITS 0x00000005 +#elif STM32_HCLK <= STM32_6WS_THRESHOLD +#define STM32_FLASHBITS 0x00000006 +#elif STM32_HCLK <= STM32_7WS_THRESHOLD +#define STM32_FLASHBITS 0x00000007 +#elif STM32_HCLK <= STM32_8WS_THRESHOLD +#define STM32_FLASHBITS 0x00000008 +#else +#error "invalid frequency at specified VDD level" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld_type1.h b/os/hal/ports/STM32/STM32F4xx/hal_lld_type1.h index 4578f49350..473a6a3fdd 100644 --- a/os/hal/ports/STM32/STM32F4xx/hal_lld_type1.h +++ b/os/hal/ports/STM32/STM32F4xx/hal_lld_type1.h @@ -1,2015 +1,2023 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/hal_lld_type1.h - * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. - * @pre This module requires the following macros to be defined in the - * @p board.h file: - * - STM32_LSECLK. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * - STM32_VDD (as hundredths of Volt). - * . - * One of the following macros must also be defined: - * - STM32F2XX for High-performance STM32F2 devices. - * - STM32F405xx, STM32F415xx, STM32F407xx, STM32F417xx, - * STM32F446xx for High-performance STM32F4 devices of - * Foundation line. - * - STM32F401xx, STM32F410xx, STM32F411xx, STM32F412xx - * for High-performance STM32F4 devices of Access line. - * - STM32F427xx, STM32F437xx, STM32F429xx, STM32F439xx, STM32F469xx, - * STM32F479xx for High-performance STM32F4 devices of Advanced line. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_TYPE1_H -#define HAL_LLD_TYPE1_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Defines the support for realtime counters in the HAL. - */ -#define HAL_IMPLEMENTS_COUNTERS TRUE - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32F205xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F205 High Performance" - -#elif defined(STM32F207xx) -#define PLATFORM_NAME "STM32F207 High Performance" - -#elif defined(STM32F215xx) -#define PLATFORM_NAME "STM32F215 High Performance" - -#elif defined(STM32F217xx) -#define PLATFORM_NAME "STM32F217 High Performance" - -#elif defined(STM32F401xx) -#define PLATFORM_NAME "STM32F401 High Performance with DSP and FPU" - -#elif defined(STM32F405xx) -#define PLATFORM_NAME "STM32F405 High Performance with DSP and FPU" - -#elif defined(STM32F407xx) -#define PLATFORM_NAME "STM32F407 High Performance with DSP and FPU" - -#elif defined(STM32F410xx) -#define PLATFORM_NAME "STM32F410 High Performance with DSP and FPU" - -#elif defined(STM32F411xx) -#define PLATFORM_NAME "STM32F411 High Performance with DSP and FPU" - -#elif defined(STM32F412xx) -#define PLATFORM_NAME "STM32F412 High Performance with DSP and FPU" - -#elif defined(STM32F415xx) -#define PLATFORM_NAME "STM32F415 High Performance with DSP and FPU" - -#elif defined(STM32F417xx) -#define PLATFORM_NAME "STM32F417 High Performance with DSP and FPU" - -#elif defined(STM32F427xx) -#define PLATFORM_NAME "STM32F427 High Performance with DSP and FPU" - -#elif defined(STM32F429xx) -#define PLATFORM_NAME "STM32F429 High Performance with DSP and FPU" - -#elif defined(STM32F437xx) -#define PLATFORM_NAME "STM32F437 High Performance with DSP and FPU" - -#elif defined(STM32F439xx) -#define PLATFORM_NAME "STM32F439 High Performance with DSP and FPU" - -#elif defined(STM32F446xx) -#define PLATFORM_NAME "STM32F446 High Performance with DSP and FPU" - -#elif defined(STM32F469xx) -#define PLATFORM_NAME "STM32F469 High Performance with DSP and FPU" - -#elif defined(STM32F479xx) -#define PLATFORM_NAME "STM32F479 High Performance with DSP and FPU" - -#else -#error "STM32F2xx/F4xx device not specified" -#endif -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -#if defined(STM32F427xx) || defined(STM32F437xx) || \ - defined(STM32F429xx) || defined(STM32F439xx) || \ - defined(STM32F469xx) || defined(STM32F479xx) || defined(__DOXYGEN__) -/** - * @brief Absolute maximum system clock. - */ -#define STM32_SYSCLK_MAX 180000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 26000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 50000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 1000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency using an external source. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 2100000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 950000 - -/** - * @brief Maximum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MAX 432000000 - -/** - * @brief Minimum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MIN 192000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 180000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 24000000 - -/** - * @brief Maximum PLLI2S output clock frequency. - */ -#define STM32_PLLI2SOUT_MAX 216000000 - -/** - * @brief Maximum PLLSAI output clock frequency. - */ -#define STM32_PLLSAIOUT_MAX 216000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX / 4) - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2) - -/** - * @brief Maximum SPI/I2S clock frequency. - */ -#define STM32_SPII2S_MAX 45000000 -#endif - -#if defined(STM32F40_41xxx) -#define STM32_SYSCLK_MAX 168000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 50000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 1000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_PLLIN_MAX 2100000 -#define STM32_PLLIN_MIN 950000 -#define STM32_PLLVCO_MAX 432000000 -#define STM32_PLLVCO_MIN 192000000 -#define STM32_PLLOUT_MAX 168000000 -#define STM32_PLLOUT_MIN 24000000 -#define STM32_PCLK1_MAX 42000000 -#define STM32_PCLK2_MAX 84000000 -#define STM32_SPII2S_MAX 42000000 -#endif - -#if defined(STM32F401xx) -#define STM32_SYSCLK_MAX 84000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 50000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 1000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_PLLIN_MAX 2100000 -#define STM32_PLLIN_MIN 950000 -#define STM32_PLLVCO_MAX 432000000 -#define STM32_PLLVCO_MIN 192000000 -#define STM32_PLLOUT_MAX 84000000 -#define STM32_PLLOUT_MIN 24000000 -#define STM32_PCLK1_MAX 42000000 -#define STM32_PCLK2_MAX 84000000 -#define STM32_SPII2S_MAX 42000000 -#endif - -#if defined(STM32F410xx) || defined(STM32F411xx) || \ - defined(STM32F412xx) -#define STM32_SYSCLK_MAX 100000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 50000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 1000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_PLLIN_MAX 2100000 -#define STM32_PLLIN_MIN 950000 -#define STM32_PLLVCO_MAX 432000000 -#define STM32_PLLVCO_MIN 100000000 -#define STM32_PLLOUT_MAX 100000000 -#define STM32_PLLOUT_MIN 24000000 -#define STM32_PCLK1_MAX 50000000 -#define STM32_PCLK2_MAX 100000000 -#define STM32_SPII2S_MAX 50000000 -#endif - -#if defined(STM32F446xx) -#define STM32_SYSCLK_MAX 180000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 50000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 1000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_PLLIN_MAX 2100000 -#define STM32_PLLIN_MIN 950000 -#define STM32_PLLVCO_MAX 432000000 -#define STM32_PLLVCO_MIN 100000000 -#define STM32_PLLOUT_MAX 180000000 -#define STM32_PLLOUT_MIN 12500000 -#define STM32_PLLI2SOUT_MAX 216000000 -#define STM32_PLLSAIOUT_MAX 216000000 -#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX / 4) -#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2) -#define STM32_SPII2S_MAX 45000000 -#endif - -#if defined(STM32F2XX) -#define STM32_SYSCLK_MAX 120000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 26000000 -#define STM32_HSECLK_MIN 1000000 -#define STM32_HSECLK_BYP_MIN 1000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_PLLIN_MAX 2000000 -#define STM32_PLLIN_MIN 950000 -#define STM32_PLLVCO_MAX 432000000 -#define STM32_PLLVCO_MIN 192000000 -#define STM32_PLLOUT_MAX 120000000 -#define STM32_PLLOUT_MIN 24000000 -#define STM32_PCLK1_MAX 30000000 -#define STM32_PCLK2_MAX 60000000 -#define STM32_SPII2S_MAX 30000000 -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 16000000 /**< High speed internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_VOS_SCALE3 0x00004000 -#define STM32_VOS_SCALE2 0x00008000 -#define STM32_VOS_SCALE1 0x0000C000 -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ -#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ -#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ -#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ -#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW mask. */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ -#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ -#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ - -#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ - -#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ -#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ -#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ - -#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */ -#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */ -#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */ - -#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ -#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ -#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ -#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ -#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ -#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ - -#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ -#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ -#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ -#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ -#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ -#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ - -#define STM32_MCO2SEL_MASK (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. */ - -/** - * @name RCC_PLLI2SCFGR register bits definitions - * @{ - */ -#define STM32_PLLI2SM_MASK (31 << 0) /**< PLLI2SM mask. */ -#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ -#define STM32_PLLI2SP_MASK (3 << 16) /**< PLLI2SP mask. */ -#define STM32_PLLI2SP_DIV2 (0 << 16) /**< PLLI2S clock divided by 2. */ -#define STM32_PLLI2SP_DIV4 (1 << 16) /**< PLLI2S clock divided by 4. */ -#define STM32_PLLI2SP_DIV6 (2 << 16) /**< PLLI2S clock divided by 6. */ -#define STM32_PLLI2SP_DIV8 (3 << 16) /**< PLLI2S clock divided by 8. */ -#define STM32_PLLI2SSRC_MASK (1 << 22) /**< PLLI2SSRC mask. */ -#define STM32_PLLI2SSRC_PLLSRC (0 << 22) /**< PLLI2SSRC is selected PLL - source. */ -#define STM32_PLLI2SSRC_CKIN (1 << 22) /**< PLLI2SSRC is I2S_CKIN. */ -#define STM32_PLLI2SQ_MASK (15 << 24) /**< PLLI2SQ mask. */ -#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ -/** @} */ - -/** - * @name RCC_PLLSAICFGR register bits definitions - * @{ - */ -#define STM32_PLLSAIM_MASK (31 << 0) /**< PLLSAIM mask. */ -#define STM32_PLLSAIN_MASK (511 << 6) /**< PLLSAIN mask. */ -#define STM32_PLLSAIP_MASK (3 << 16) /**< PLLSAIP mask. */ -#define STM32_PLLSAIP_DIV2 (0 << 16) /**< PLLSAI clock divided by 2. */ -#define STM32_PLLSAIP_DIV4 (1 << 16) /**< PLLSAI clock divided by 4. */ -#define STM32_PLLSAIP_DIV6 (2 << 16) /**< PLLSAI clock divided by 6. */ -#define STM32_PLLSAIP_DIV8 (3 << 16) /**< PLLSAI clock divided by 8. */ -#define STM32_PLLSAIQ_MASK (15 << 24) /**< PLLSAIQ mask. */ -#define STM32_PLLSAIR_MASK (7 << 28) /**< PLLSAIR mask. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ -/** @} */ - -/** - * @name RCC_DCKCFGR register bits definitions - * @{ - */ -#define STM32_PLLI2SDIVQ_MASK (31 << 0) /**< PLLI2SDIVQ mask. */ -#define STM32_PLLSAIDIVQ_MASK (31 << 8) /**< PLLSAIDIVQ mask. */ - -#define STM32_PLLSAIDIVR_MASK (3 << 16) /**< PLLSAIDIVR mask. */ -#define STM32_PLLSAIDIVR_DIV2 (0 << 16) /**< LCD_CLK is R divided by 2. */ -#define STM32_PLLSAIDIVR_DIV4 (1 << 16) /**< LCD_CLK is R divided by 4. */ -#define STM32_PLLSAIDIVR_DIV8 (2 << 16) /**< LCD_CLK is R divided by 8. */ -#define STM32_PLLSAIDIVR_DIV16 (3 << 16) /**< LCD_CLK is R divided by 16.*/ -#define STM32_PLLSAIDIVR_OFF 0xFFFFFFFFU /**< LCD CLK is not required. */ - -#define STM32_SAI1SEL_MASK (3 << 20) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_PLLSAI (0 << 20) /**< SAI1 source is PLLSAI. */ -#define STM32_SAI1SEL_PLLI2S (1 << 20) /**< SAI1 source is PLLI2S. */ -#define STM32_SAI1SEL_PLLR (2 << 20) /**< SAI1 source is PLLR. */ -#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ - -#define STM32_SAI2SEL_MASK (3 << 22) /**< SAI2SEL mask. */ -#define STM32_SAI2SEL_PLLSAI (0 << 22) /**< SAI2 source is PLLSAI. */ -#define STM32_SAI2SEL_PLLI2S (1 << 22) /**< SAI2 source is PLLI2S. */ -#define STM32_SAI2SEL_PLLR (2 << 22) /**< SAI2 source is PLLR. */ -#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ - -#define STM32_TIMPRE_MASK (1 << 24) /**< TIMPRE mask. */ -#define STM32_TIMPRE_PCLK (0 << 24) /**< TIM clocks from PCLKx. */ -#define STM32_TIMPRE_HCLK (1 << 24) /**< TIM clocks from HCLK. */ - -#define STM32_I2S1SEL_MASK (3 << 25) /**< I2S1SEL mask. */ -#define STM32_I2S1SEL_PLLR (0 << 25) /**< I2S1 source is PLLR. */ -#define STM32_I2S1SEL_AFIN (1 << 25) /**< I2S1 source is AF Input. */ -#define STM32_I2S1SEL_MCO1 (2 << 25) /**< I2S1 source is MCO1. */ -#define STM32_I2S1SEL_OFF 0xFFFFFFFFU /**< I2S1 clock is not required.*/ - -#define STM32_I2S2SEL_MASK (3 << 27) /**< I2S2SEL mask. */ -#define STM32_I2S2SEL_PLLR (0 << 27) /**< I2S2 source is PLLR. */ -#define STM32_I2S2SEL_AFIN (1 << 27) /**< I2S2 source is AF Input. */ -#define STM32_I2S2SEL_MCO1 (2 << 27) /**< I2S2 source is MCO1. */ -#define STM32_I2S2SEL_OFF 0xFFFFFFFFU /**< I2S2 clock is not required.*/ - -#define STM32_DSISEL_MASK (1 << 28) /**< DSISEL mask. */ -#define STM32_DSISEL_PHY (0 << 28) /**< DSI source is DSI-PSY. */ -#define STM32_DSISEL_PLLR (1 << 28) /**< DSI source is PLLR. */ -/** @} */ - -/** - * @name RCC_DCKCFGR2 register bits definitions - * @{ - */ -#define STM32_I2C1SEL_MASK (3 << 22) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK1 (0 << 22) /**< I2C1 source is APB/PCLK1. */ -#define STM32_I2C1SEL_SYSCLK (1 << 22) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI (2 << 22) /**< I2C1 source is HSI. */ - -#define STM32_CECSEL_MASK (1 << 26) /**< CECSEL mask. */ -#define STM32_CECSEL_LSE (0 << 26) /**< CEC source is LSE. */ -#define STM32_CECSEL_HSIDIV488 (1 << 26) /**< CEC source is HSI/488. */ - -#define STM32_CK48MSEL_MASK (1 << 27) /**< CK48MSEL mask. */ -#define STM32_CK48MSEL_PLL (0 << 27) /**< PLL48CLK source is PLL. */ -#define STM32_CK48MSEL_PLLSAI (1 << 27) /**< PLL48CLK source is PLLSAI. */ -#define STM32_CK48MSEL_PLLALT (1 << 27) /**< Alias. */ - -#define STM32_SDMMCSEL_MASK (1 << 28) /**< SDMMCSEL mask. */ -#define STM32_SDMMCSEL_PLL48CLK (0 << 28) /**< SDMMC source is PLL48CLK. */ -#define STM32_SDMMCSEL_SYSCLK (1 << 28) /**< SDMMC source is SYSCLK. */ - -#define STM32_SPDIFSEL_MASK (1 << 29) /**< SPDIFSEL mask. */ -#define STM32_SPDIFSEL_PLLI2S (0 << 29) /**< SPDIF source is PLLI2S. */ -#define STM32_SPDIFSEL_PLL (1 << 29) /**< SPDIF source is PLL. */ - -#define STM32_LPTIM1SEL_MASK (3 << 30) /**< LPTIM1 mask. */ -#define STM32_LPTIM1SEL_APB (0 << 30) /**< LPTIM1 source is APB. */ -#define STM32_LPTIM1SEL_HSI (1 << 30) /**< LPTIM1 source is HSI. */ -#define STM32_LPTIM1SEL_LSI (2 << 30) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_LSE (3 << 30) /**< LPTIM1 source is LSE. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables the backup RAM regulator. - */ -#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__) -#define STM32_BKPRAM_ENABLE FALSE -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief USB/SDIO clock setting. - */ -#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) -#define STM32_CLOCK48_REQUIRED TRUE -#endif - -/** - * @brief Main clock source selection. - * @note If the selected clock source is not the PLL then the PLL is not - * initialized and started. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -#if defined(STM32F4XX) || defined(__DOXYGEN__) -/** - * @brief Clock source for the PLLs. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 8 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 192..432. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 336 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 -#endif - -/** - * @brief PLLQ multiplier value. - * @note The allowed values are 2..15. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 7 -#endif - -/** - * @brief PLLR divider value. - * @note The allowed values are 2..7. - * @note The default value is calculated for a 96MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLR_VALUE 4 -#endif - -#else /* !defined(STM32F4XX) */ -/** - * @brief Clock source for the PLLs. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 8 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 192..432. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 240 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 -#endif - -/** - * @brief PLLQ multiplier value. - * @note The allowed values are 2..15. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 5 -#endif -#endif /* !defined(STM32F4XX) */ - -/** - * @brief I2S clock source (post-PLL). - * @note Not all devices have this setting, it is alternative to - * @p STM32_PLLI2SSRC. - */ -#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__) -#define STM32_I2SSRC STM32_I2SSRC_CKIN -#endif - -/** - * @brief I2S clock source (pre-PLL). - * @note Not all devices have this setting, it is alternative to - * @p STM32_I2SSRC. - */ -#if !defined(STM32_PLLI2SSRC) || defined(__DOXYGEN__) -#define STM32_PLLI2SSRC STM32_PLLI2SSRC_CKIN -#endif - -/** - * @brief I2S external clock value, zero if not present. - * @note Not all devices have this setting. - */ -#if !defined(STM32_I2SCKIN_VALUE) || defined(__DOXYGEN__) -#define STM32_I2SCKIN_VALUE 0 -#endif - -/** - * @brief PLLI2SN multiplier value. - * @note The allowed values are 192..432, except for - * STM32F446 where values are 50...432. - * @note The default value is calculated for a 96MHz I2S clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SN_VALUE 192 -#endif - -/** - * @brief PLLI2SM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 96MHz I2S clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLI2SM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SM_VALUE 4 -#endif - -/** - * @brief PLLI2SR divider value. - * @note The allowed values are 2..7. - * @note The default value is calculated for a 96MHz I2S clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SR_VALUE 4 -#endif - -/** - * @brief PLLI2SP divider value. - * @note The allowed values are 2, 4, 6 and 8. - */ -#if !defined(STM32_PLLI2SP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SP_VALUE 4 -#endif - -/** - * @brief PLLI2SQ divider value. - * @note The allowed values are 2..15. - */ -#if !defined(STM32_PLLI2SQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SQ_VALUE 4 -#endif - -/** - * @brief PLLI2SDIVQ divider value (SAI clock divider). - * @note The allowed values are 1..32. - */ -#if !defined(STM32_PLLI2SDIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SDIVQ_VALUE 1 -#endif - -/** - * @brief PLLSAIM value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 96MHz SAI clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSAIM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIM_VALUE 4 -#endif - -/** - * @brief PLLSAIN value. - * @note The allowed values are 50..432. - * @note The default value is calculated for a 96MHz SAI clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSAIN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIN_VALUE 192 -#endif - -/** - * @brief PLLSAIM value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 96MHz SAI clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSAIM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIM_VALUE 4 -#endif - -/** - * @brief PLLSAIR value. - * @note The allowed values are 2..7. - */ -#if !defined(STM32_PLLSAIR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIR_VALUE 4 -#endif - -/** - * @brief PLLSAIP divider value. - * @note The allowed values are 2, 4, 6 and 8. - */ -#if !defined(STM32_PLLSAIP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIP_VALUE 8 -#endif - -/** - * @brief PLLSAIQ value. - * @note The allowed values are 2..15. - */ -#if !defined(STM32_PLLSAIQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIQ_VALUE 4 -#endif - -/** - * @brief PLLSAIDIVR divider value (SAI clock divider). - */ -#if !defined(STM32_PLLSAIDIVR) || defined(__DOXYGEN__) -#define STM32_PLLSAIDIVR STM32_PLLSAIDIVR_OFF -#endif - -/** - * @brief PLLSAIDIVQ divider value (LCD clock divider). - * @note The allowed values are 1..32. - */ -#if !defined(STM32_PLLSAIDIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIDIVQ_VALUE 1 -#endif - -/** - * @brief SAI1SEL value (SAI1 clock source). - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#endif - -/** - * @brief SAI2SEL value (SAI2 clock source). - */ -#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#endif - -/** - * @brief TIM prescaler clock source. - */ -#if !defined(STM32_TIMPRE) || defined(__DOXYGEN__) -#define STM32_TIMPRE STM32_TIMPRE_PCLK -#endif - -/** - * @brief PLL48CLK clock source. - */ -#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) -#define STM32_CK48MSEL STM32_CK48MSEL_PLL -#endif - -/** - * @brief AHB prescaler value. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief RTC HSE prescaler value. - */ -#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) -#define STM32_RTCPRE_VALUE 8 -#endif - -/** - * @brief MCO1 clock source value. - * @note The default value outputs HSI clock on MCO1 pin. - */ -#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#endif - -/** - * @brief MCO1 prescaler value. - * @note The default value outputs HSI clock on MCO1 pin. - */ -#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#endif - -/** - * @brief MCO2 clock source value. - * @note The default value outputs SYSCLK / 5 on MCO2 pin. - */ -#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#endif - -/** - * @brief MCO2 prescaler value. - * @note The default value outputs SYSCLK / 5 on MCO2 pin. - */ -#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if defined(STM32F4XX) || defined(__DOXYGEN__) -/* - * Configuration-related checks. - */ -#if !defined(STM32F4xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined" -#endif - -#if defined(STM32F405xx) && !defined(STM32F405_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F405_MCUCONF not defined" -#endif - -#if defined(STM32F415xx) && !defined(STM32F415_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F415_MCUCONF not defined" -#endif - -#if defined(STM32F407xx) && !defined(STM32F407_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F407_MCUCONF not defined" -#endif - -#if defined(STM32F417xx) && !defined(STM32F417_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F417_MCUCONF not defined" -#endif - -#else /* !defined(STM32F4XX) */ -/* - * Configuration-related checks. - */ -#if !defined(STM32F2xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F2xx_MCUCONF not defined" -#endif -#endif /* !defined(STM32F4XX) */ - -/** - * @name Maximum frequency thresholds, wait states and - * parallelism for flash access. - * @{ - */ -#if defined(STM32F429_439xx) || defined(STM32F427_437xx) || \ - defined(STM32F40_41xxx) || defined(STM32F446xx) || \ - defined(STM32F469_479xx) || defined(__DOXYGEN__) -#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 60000000 -#define STM32_2WS_THRESHOLD 90000000 -#define STM32_3WS_THRESHOLD 120000000 -#define STM32_4WS_THRESHOLD 150000000 -#define STM32_5WS_THRESHOLD 180000000 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 2 -#elif (STM32_VDD >= 240) && (STM32_VDD < 270) -#define STM32_0WS_THRESHOLD 24000000 -#define STM32_1WS_THRESHOLD 48000000 -#define STM32_2WS_THRESHOLD 72000000 -#define STM32_3WS_THRESHOLD 96000000 -#define STM32_4WS_THRESHOLD 120000000 -#define STM32_5WS_THRESHOLD 144000000 -#define STM32_6WS_THRESHOLD 168000000 -#define STM32_7WS_THRESHOLD 180000000 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 210) && (STM32_VDD < 240) -#define STM32_0WS_THRESHOLD 22000000 -#define STM32_1WS_THRESHOLD 44000000 -#define STM32_2WS_THRESHOLD 66000000 -#define STM32_3WS_THRESHOLD 88000000 -#define STM32_4WS_THRESHOLD 110000000 -#define STM32_5WS_THRESHOLD 132000000 -#define STM32_6WS_THRESHOLD 154000000 -#define STM32_7WS_THRESHOLD 176000000 -#define STM32_8WS_THRESHOLD 180000000 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 180) && (STM32_VDD < 210) -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 120000000 -#define STM32_6WS_THRESHOLD 140000000 -#define STM32_7WS_THRESHOLD 168000000 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 0 -#else -#error "invalid VDD voltage specified" -#endif - -#elif defined(STM32F412xx) -#if (STM32_VDD >= 270) && (STM32_VDD <= 360) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 64000000 -#define STM32_2WS_THRESHOLD 90000000 -#define STM32_3WS_THRESHOLD 100000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 2 -#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 100000000 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#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 100000000 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 170) && (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 100000000 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 0 -#else -#error "invalid VDD voltage specified" -#endif - -#elif defined(STM32F410xx) || defined(STM32F411xx) -#if (STM32_VDD >= 270) && (STM32_VDD <= 360) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 64000000 -#define STM32_2WS_THRESHOLD 90000000 -#define STM32_3WS_THRESHOLD 100000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 2 -#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 100000000 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#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 100000000 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 171) && (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 100000000 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 0 - -#else -#error "invalid VDD voltage specified" -#endif - -#elif defined(STM32F401xx) -#if (STM32_VDD >= 270) && (STM32_VDD <= 360) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 60000000 -#define STM32_2WS_THRESHOLD 84000000 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 2 - -#elif (STM32_VDD >= 240) && (STM32_VDD < 270) -#define STM32_0WS_THRESHOLD 24000000 -#define STM32_1WS_THRESHOLD 48000000 -#define STM32_2WS_THRESHOLD 72000000 -#define STM32_3WS_THRESHOLD 84000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 - -#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 84000000 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 - -#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 84000000 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 0 - -#else -#error "invalid VDD voltage specified" -#endif - -#else /* STM32F2XX */ -#if (STM32_VDD >= 270) && (STM32_VDD <= 360) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 60000000 -#define STM32_2WS_THRESHOLD 90000000 -#define STM32_3WS_THRESHOLD 120000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 2 -#elif (STM32_VDD >= 240) && (STM32_VDD < 270) -#define STM32_0WS_THRESHOLD 24000000 -#define STM32_1WS_THRESHOLD 48000000 -#define STM32_2WS_THRESHOLD 72000000 -#define STM32_3WS_THRESHOLD 96000000 -#define STM32_4WS_THRESHOLD 120000000 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 210) && (STM32_VDD < 240) -#define STM32_0WS_THRESHOLD 18000000 -#define STM32_1WS_THRESHOLD 36000000 -#define STM32_2WS_THRESHOLD 54000000 -#define STM32_3WS_THRESHOLD 72000000 -#define STM32_4WS_THRESHOLD 90000000 -#define STM32_5WS_THRESHOLD 108000000 -#define STM32_6WS_THRESHOLD 120000000 -#define STM32_7WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 180) && (STM32_VDD < 210) -#define STM32_0WS_THRESHOLD 16000000 -#define STM32_1WS_THRESHOLD 32000000 -#define STM32_2WS_THRESHOLD 48000000 -#define STM32_3WS_THRESHOLD 64000000 -#define STM32_4WS_THRESHOLD 80000000 -#define STM32_5WS_THRESHOLD 96000000 -#define STM32_6WS_THRESHOLD 112000000 -#define STM32_7WS_THRESHOLD 120000000 -#define STM32_FLASH_PSIZE 0 - -#else -#error "invalid VDD voltage specified" -#endif -#endif /* STM32F2XX */ -/** @} */ - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_I2SSRC" -#endif - -#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_I2SSRC" -#endif - -#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SAI1SEL" -#endif - -#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SAI2SEL" -#endif -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#else /* STM32_HSECLK != 0 */ -#if defined(STM32_HSE_BYPASS) -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_BYP_MAX)" -#endif -#else /* !defined(STM32_HSE_BYPASS) */ -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif -#endif /* !defined(STM32_HSE_BYPASS) */ -#endif /* STM32_HSECLK != 0 */ -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ - ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_I2SSRC" -#endif - -#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_PLLI2SSRC" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief Clock frequency feeding PLLs. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSRCCLK STM32_HSECLK -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLSRCCLK STM32_HSICLK -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/** - * @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 PLL input clock frequency. - */ -#define STM32_PLLCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) - -/* - * PLLs input frequency range check. - */ -#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_CLOCK48_REQUIRED && \ - STM32_HAS_RCC_CK48MSEL && \ - (STM32_CK48MSEL == STM32_CK48MSEL_PLL)) || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ - (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 6) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLP STM32_PLLP_DIV2 -#elif STM32_PLLP_VALUE == 4 -#define STM32_PLLP STM32_PLLP_DIV4 -#elif STM32_PLLP_VALUE == 6 -#define STM32_PLLP STM32_PLLP_DIV6 -#elif STM32_PLLP_VALUE == 8 -#define STM32_PLLP STM32_PLLP_DIV8 -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -#if defined(STM32F4XX) || defined(__DOXYGEN__) -/** - * @brief STM32_PLLR field. - */ -#if ((STM32_PLLR_VALUE >= 2) && (STM32_PLLR_VALUE <= 7)) || \ - defined(__DOXYGEN__) -#define STM32_PLLR (STM32_PLLR_VALUE << 28) -#else -#error "invalid STM32_PLLR_VALUE value specified" -#endif -#else /* !defined(STM32F4XX) */ -#define STM32_PLLR 0 -#endif /* !defined(STM32F4XX) */ - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) - -/* - * PLL output frequency range check. - */ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/* Calculating VOS settings, it is different for each sub-platform.*/ -#if defined(STM32F429_439xx) || defined(STM32F427_437xx) || \ - defined(STM32F446xx) || defined(STM32F469_479xx) || \ - defined(__DOXYGEN__) -#if STM32_SYSCLK <= 120000000 -#define STM32_VOS STM32_VOS_SCALE3 -#define STM32_OVERDRIVE_REQUIRED FALSE -#elif STM32_SYSCLK <= 144000000 -#define STM32_VOS STM32_VOS_SCALE2 -#define STM32_OVERDRIVE_REQUIRED FALSE -#elif STM32_SYSCLK <= 168000000 -#define STM32_VOS STM32_VOS_SCALE1 -#define STM32_OVERDRIVE_REQUIRED FALSE -#else -#define STM32_VOS STM32_VOS_SCALE1 -#define STM32_OVERDRIVE_REQUIRED TRUE -#endif - -#elif defined(STM32F40_41xxx) -#if STM32_SYSCLK <= 144000000 -#define STM32_VOS STM32_VOS_SCALE2 -#else -#define STM32_VOS STM32_VOS_SCALE1 -#endif -#define STM32_OVERDRIVE_REQUIRED FALSE - -#elif defined(STM32F401xx) -#if STM32_SYSCLK <= 60000000 -#define STM32_VOS STM32_VOS_SCALE3 -#else -#define STM32_VOS STM32_VOS_SCALE2 -#endif -#define STM32_OVERDRIVE_REQUIRED FALSE - -#elif defined(STM32F410xx) || defined(STM32F411xx) || \ - defined(STM32F412xx) -#if STM32_SYSCLK <= 64000000 -#define STM32_VOS STM32_VOS_SCALE3 -#elif STM32_SYSCLK <= 84000000 -#define STM32_VOS STM32_VOS_SCALE2 -#else -#define STM32_VOS STM32_VOS_SCALE1 -#endif -#define STM32_OVERDRIVE_REQUIRED FALSE - -#else /* STM32F2XX */ -#define STM32_OVERDRIVE_REQUIRED FALSE -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/* - * PLLI2S enable check. - */ -#if (STM32_HAS_RCC_PLLI2S && \ - (STM32_CLOCK48_REQUIRED && \ - (STM32_HAS_RCC_CK48MSEL && \ - STM32_RCC_CK48MSEL_USES_I2S && \ - (STM32_CK48MSEL == STM32_CK48MSEL_PLLALT)) || \ - (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S))) || \ - defined(__DOXYGEN__) - -/** - * @brief PLLI2S activation flag. - */ -#define STM32_ACTIVATE_PLLI2S TRUE -#else -#define STM32_ACTIVATE_PLLI2S FALSE -#endif - -/** - * @brief STM32_PLLI2SM field. - */ -#if ((STM32_PLLI2SM_VALUE >= 2) && (STM32_PLLI2SM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SM (STM32_PLLI2SM_VALUE << 0) -#else -#error "invalid STM32_PLLI2SM_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SN field. - */ -#if ((STM32_PLLI2SN_VALUE >= 50) && (STM32_PLLI2SN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) -#else -#error "invalid STM32_PLLI2SN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SP field. - */ -#if (STM32_PLLI2SP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLI2SP STM32_PLLI2SP_DIV2 -#elif STM32_PLLI2SP_VALUE == 4 -#define STM32_PLLI2SP STM32_PLLI2SP_DIV4 -#elif STM32_PLLI2SP_VALUE == 6 -#define STM32_PLLI2SP STM32_PLLI2SP_DIV6 -#elif STM32_PLLI2SP_VALUE == 8 -#define STM32_PLLI2SP STM32_PLLI2SP_DIV8 -#else -#error "invalid STM32_PLLI2SP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SQ field. - */ -#if ((STM32_PLLI2SQ_VALUE >= 2) && (STM32_PLLI2SQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SQ (STM32_PLLI2SQ_VALUE << 24) -#else -#error "invalid STM32_PLLI2SQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SDIVQ field. - */ -#if ((STM32_PLLI2SDIVQ_VALUE >= 1) && (STM32_PLLI2SDIVQ_VALUE <= 32)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SDIVQ ((STM32_PLLI2SQ_VALUE - 1) << 0) -#else -#error "invalid STM32_PLLI2SDIVQ_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 PLLI2S input clock frequency. - */ -#if STM32_HAS_RCC_I2SPLLSRC || defined(__DOXYGEN__) -#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLI2SM_VALUE) -#elif STM32_PLLI2SSRC == STM32_PLLI2SSRC_CKIN -#define STM32_PLLI2SCLKIN (STM32_I2SCKIN_VALUE / STM32_PLLI2SM_VALUE) -#else -#error "invalid STM32_PLLI2SSRC value specified" -#endif -#else -#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) -#endif - -/** - * @brief PLLI2S VCO frequency. - */ -#define STM32_PLLI2SVCO (STM32_PLLI2SCLKIN * 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 P output clock frequency. - */ -#define STM32_PLLI2S_P_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SP_VALUE) - -/** - * @brief PLLI2S Q output clock frequency. - */ -#define STM32_PLLI2S_Q_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SQ_VALUE) - -/** - * @brief PLLI2S R output clock frequency. - */ -#define STM32_PLLI2S_R_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) - -/* - * PLLSAI enable check. - */ -#if (STM32_HAS_RCC_PLLSAI && \ - (STM32_CLOCK48_REQUIRED && \ - (STM32_HAS_RCC_CK48MSEL && \ - !STM32_RCC_CK48MSEL_USES_I2S && \ - (STM32_CK48MSEL == STM32_CK48MSEL_PLLALT)) || \ - (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI))) || \ - (STM32_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF) || \ - defined(__DOXYGEN__) -/** - * @brief PLLSAI activation flag. - */ -#define STM32_ACTIVATE_PLLSAI TRUE -#else -#define STM32_ACTIVATE_PLLSAI FALSE -#endif - -/** - * @brief STM32_PLLSAIM field. - */ -#if ((STM32_PLLSAIM_VALUE >= 2) && (STM32_PLLSAIM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIM (STM32_PLLSAIM_VALUE << 0) -#else -#error "invalid STM32_PLLSAIM_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIN field. - */ -#if ((STM32_PLLSAIN_VALUE >= 49) && (STM32_PLLSAIN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIN (STM32_PLLSAIN_VALUE << 6) -#else -#error "invalid STM32_PLLSAIN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIQ field. - */ -#if ((STM32_PLLSAIQ_VALUE >= 2) && (STM32_PLLSAIQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIQ (STM32_PLLSAIQ_VALUE << 24) -#else -#error "invalid STM32_PLLSAIQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIDIVQ_VALUE field. - */ -#if ((STM32_PLLSAIDIVQ_VALUE >= 1) && (STM32_PLLSAIDIVQ_VALUE <= 32)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIDIVQ ((STM32_PLLSAIDIVQ_VALUE - 1) << 8) -#else -#error "invalid STM32_PLLSAIDIVQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIR field. - */ -#if ((STM32_PLLSAIR_VALUE >= 2) && (STM32_PLLSAIR_VALUE <= 7)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIR (STM32_PLLSAIR_VALUE << 28) -#else -#error "invalid STM32_PLLSAIR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIP field. - */ - -#if (STM32_PLLSAIP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAIP STM32_PLLSAIP_DIV2 - -#elif STM32_PLLSAIP_VALUE == 4 -#define STM32_PLLSAIP STM32_PLLSAIP_DIV4 - -#elif STM32_PLLSAIP_VALUE == 6 -#define STM32_PLLSAIP STM32_PLLSAIP_DIV6 - -#elif STM32_PLLSAIP_VALUE == 8 -#define STM32_PLLSAIP STM32_PLLSAIP_DIV8 - -#else -#error "invalid STM32_PLLSAIP_VALUE value specified" -#endif - -/** - * @brief PLLSAI input clock frequency. - */ -#if defined(STM32F446xx) -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSAICLKIN (STM32_HSECLK / STM32_PLLSAIM_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLSAICLKIN (STM32_HSICLK / STM32_PLLSAIM_VALUE) -#else -#error "invalid STM32_PLLSRC value specified" -#endif -#else /* !defined(STM32F446xx) */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSAICLKIN (STM32_HSECLK / STM32_PLLM_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLSAICLKIN (STM32_HSICLK / STM32_PLLM_VALUE) -#else -#error "invalid STM32_PLLSRC value specified" -#endif -#endif /* defined(STM32F446xx) */ - -/** - * @brief PLLSAI VCO frequency. - */ -#define STM32_PLLSAIVCO (STM32_PLLSAICLKIN * STM32_PLLSAIN_VALUE) - -/* - * PLLSAI VCO frequency range check. - */ -#if (STM32_PLLSAIVCO < STM32_PLLVCO_MIN) || \ - (STM32_PLLSAIVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLSAIVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI P output clock frequency. - */ -#define STM32_PLLSAI_P_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIP_VALUE) - -/** - * @brief PLLSAI Q output clock frequency. - */ -#define STM32_PLLSAI_Q_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIQ_VALUE) - -/** - * @brief PLLSAI R output clock frequency. - */ -#define STM32_PLLSAI_R_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIR_VALUE) - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_TYPE1_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/hal_lld_type1.h + * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - STM32_LSECLK. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * - STM32_VDD (as hundredths of Volt). + * . + * One of the following macros must also be defined: + * - STM32F2XX for High-performance STM32F2 devices. + * - STM32F405xx, STM32F415xx, STM32F407xx, STM32F417xx, + * STM32F446xx for High-performance STM32F4 devices of + * Foundation line. + * - STM32F401xx, STM32F410xx, STM32F411xx, STM32F412xx + * for High-performance STM32F4 devices of Access line. + * - STM32F427xx, STM32F437xx, STM32F429xx, STM32F439xx, STM32F469xx, + * STM32F479xx for High-performance STM32F4 devices of Advanced line. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_TYPE1_H +#define HAL_LLD_TYPE1_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +#define HAL_IMPLEMENTS_COUNTERS TRUE + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32F205xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F205 High Performance" + +#elif defined(STM32F207xx) +#define PLATFORM_NAME "STM32F207 High Performance" + +#elif defined(STM32F215xx) +#define PLATFORM_NAME "STM32F215 High Performance" + +#elif defined(STM32F217xx) +#define PLATFORM_NAME "STM32F217 High Performance" + +#elif defined(STM32F401xx) +#define PLATFORM_NAME "STM32F401 High Performance with DSP and FPU" + +#elif defined(STM32F405xx) +#define PLATFORM_NAME "STM32F405 High Performance with DSP and FPU" + +#elif defined(STM32F407xx) +#define PLATFORM_NAME "STM32F407 High Performance with DSP and FPU" + +#elif defined(STM32F410xx) +#define PLATFORM_NAME "STM32F410 High Performance with DSP and FPU" + +#elif defined(STM32F411xx) +#define PLATFORM_NAME "STM32F411 High Performance with DSP and FPU" + +#elif defined(STM32F412xx) +#define PLATFORM_NAME "STM32F412 High Performance with DSP and FPU" + +#elif defined(STM32F415xx) +#define PLATFORM_NAME "STM32F415 High Performance with DSP and FPU" + +#elif defined(STM32F417xx) +#define PLATFORM_NAME "STM32F417 High Performance with DSP and FPU" + +#elif defined(STM32F427xx) +#define PLATFORM_NAME "STM32F427 High Performance with DSP and FPU" + +#elif defined(STM32F429xx) +#define PLATFORM_NAME "STM32F429 High Performance with DSP and FPU" + +#elif defined(STM32F437xx) +#define PLATFORM_NAME "STM32F437 High Performance with DSP and FPU" + +#elif defined(STM32F439xx) +#define PLATFORM_NAME "STM32F439 High Performance with DSP and FPU" + +#elif defined(STM32F446xx) +#define PLATFORM_NAME "STM32F446 High Performance with DSP and FPU" + +#elif defined(STM32F469xx) +#define PLATFORM_NAME "STM32F469 High Performance with DSP and FPU" + +#elif defined(STM32F479xx) +#define PLATFORM_NAME "STM32F479 High Performance with DSP and FPU" + +#else +#error "STM32F2xx/F4xx device not specified" +#endif +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +#if defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || defined(__DOXYGEN__) +/** + * @brief Absolute maximum system clock. + */ +#define STM32_SYSCLK_MAX 180000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 26000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 50000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency using an external source. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 2100000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 950000 + +/** + * @brief Maximum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MAX 432000000 + +/** + * @brief Minimum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MIN 192000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 180000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 24000000 + +/** + * @brief Maximum PLLI2S output clock frequency. + */ +#define STM32_PLLI2SOUT_MAX 216000000 + +/** + * @brief Maximum PLLSAI output clock frequency. + */ +#define STM32_PLLSAIOUT_MAX 216000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX / 4) + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2) + +/** + * @brief Maximum SPI/I2S clock frequency. + */ +#define STM32_SPII2S_MAX 45000000 +#endif + +#if defined(STM32F40_41xxx) +#define STM32_SYSCLK_MAX 168000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 50000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 1000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_PLLIN_MAX 2100000 +#define STM32_PLLIN_MIN 950000 +#define STM32_PLLVCO_MAX 432000000 +#define STM32_PLLVCO_MIN 192000000 +#define STM32_PLLOUT_MAX 168000000 +#define STM32_PLLOUT_MIN 24000000 +#define STM32_PCLK1_MAX 42000000 +#define STM32_PCLK2_MAX 84000000 +#define STM32_SPII2S_MAX 42000000 +#endif + +#if defined(STM32F401xx) +#define STM32_SYSCLK_MAX 84000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 50000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 1000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_PLLIN_MAX 2100000 +#define STM32_PLLIN_MIN 950000 +#define STM32_PLLVCO_MAX 432000000 +#define STM32_PLLVCO_MIN 192000000 +#define STM32_PLLOUT_MAX 84000000 +#define STM32_PLLOUT_MIN 24000000 +#define STM32_PCLK1_MAX 42000000 +#define STM32_PCLK2_MAX 84000000 +#define STM32_SPII2S_MAX 42000000 +#endif + +#if defined(STM32F410xx) || defined(STM32F411xx) || \ + defined(STM32F412xx) +#define STM32_SYSCLK_MAX 100000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 50000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 1000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_PLLIN_MAX 2100000 +#define STM32_PLLIN_MIN 950000 +#define STM32_PLLVCO_MAX 432000000 +#define STM32_PLLVCO_MIN 100000000 +#define STM32_PLLOUT_MAX 100000000 +#define STM32_PLLOUT_MIN 24000000 +#define STM32_PCLK1_MAX 50000000 +#define STM32_PCLK2_MAX 100000000 +#define STM32_SPII2S_MAX 50000000 +#endif + +#if defined(STM32F446xx) +#define STM32_SYSCLK_MAX 180000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 50000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 1000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_PLLIN_MAX 2100000 +#define STM32_PLLIN_MIN 950000 +#define STM32_PLLVCO_MAX 432000000 +#define STM32_PLLVCO_MIN 100000000 +#define STM32_PLLOUT_MAX 180000000 +#define STM32_PLLOUT_MIN 12500000 +#define STM32_PLLI2SOUT_MAX 216000000 +#define STM32_PLLSAIOUT_MAX 216000000 +#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX / 4) +#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2) +#define STM32_SPII2S_MAX 45000000 +#endif + +#if defined(STM32F2XX) +#define STM32_SYSCLK_MAX 120000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 26000000 +#define STM32_HSECLK_MIN 1000000 +#define STM32_HSECLK_BYP_MIN 1000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_PLLIN_MAX 2000000 +#define STM32_PLLIN_MIN 950000 +#define STM32_PLLVCO_MAX 432000000 +#define STM32_PLLVCO_MIN 192000000 +#define STM32_PLLOUT_MAX 120000000 +#define STM32_PLLOUT_MIN 24000000 +#define STM32_PCLK1_MAX 30000000 +#define STM32_PCLK2_MAX 60000000 +#define STM32_SPII2S_MAX 30000000 +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 16000000 /**< High speed internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_VOS_SCALE3 0x00004000 +#define STM32_VOS_SCALE2 0x00008000 +#define STM32_VOS_SCALE1 0x0000C000 +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ +#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ +#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ +#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ +#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW mask. */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ +#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ +#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ + +#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ + +#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ +#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ +#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ + +#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */ +#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */ +#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */ + +#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ +#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ +#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ +#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ +#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ +#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ + +#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ +#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ +#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ +#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ +#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ +#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ + +#define STM32_MCO2SEL_MASK (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. */ + +/** + * @name RCC_PLLI2SCFGR register bits definitions + * @{ + */ +#define STM32_PLLI2SM_MASK (31 << 0) /**< PLLI2SM mask. */ +#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ +#define STM32_PLLI2SP_MASK (3 << 16) /**< PLLI2SP mask. */ +#define STM32_PLLI2SP_DIV2 (0 << 16) /**< PLLI2S clock divided by 2. */ +#define STM32_PLLI2SP_DIV4 (1 << 16) /**< PLLI2S clock divided by 4. */ +#define STM32_PLLI2SP_DIV6 (2 << 16) /**< PLLI2S clock divided by 6. */ +#define STM32_PLLI2SP_DIV8 (3 << 16) /**< PLLI2S clock divided by 8. */ +#define STM32_PLLI2SSRC_MASK (1 << 22) /**< PLLI2SSRC mask. */ +#define STM32_PLLI2SSRC_PLLSRC (0 << 22) /**< PLLI2SSRC is selected PLL + source. */ +#define STM32_PLLI2SSRC_CKIN (1 << 22) /**< PLLI2SSRC is I2S_CKIN. */ +#define STM32_PLLI2SQ_MASK (15 << 24) /**< PLLI2SQ mask. */ +#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ +/** @} */ + +/** + * @name RCC_PLLSAICFGR register bits definitions + * @{ + */ +#define STM32_PLLSAIM_MASK (31 << 0) /**< PLLSAIM mask. */ +#define STM32_PLLSAIN_MASK (511 << 6) /**< PLLSAIN mask. */ +#define STM32_PLLSAIP_MASK (3 << 16) /**< PLLSAIP mask. */ +#define STM32_PLLSAIP_DIV2 (0 << 16) /**< PLLSAI clock divided by 2. */ +#define STM32_PLLSAIP_DIV4 (1 << 16) /**< PLLSAI clock divided by 4. */ +#define STM32_PLLSAIP_DIV6 (2 << 16) /**< PLLSAI clock divided by 6. */ +#define STM32_PLLSAIP_DIV8 (3 << 16) /**< PLLSAI clock divided by 8. */ +#define STM32_PLLSAIQ_MASK (15 << 24) /**< PLLSAIQ mask. */ +#define STM32_PLLSAIR_MASK (7 << 28) /**< PLLSAIR mask. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ +/** @} */ + +/** + * @name RCC_DCKCFGR register bits definitions + * @{ + */ +#define STM32_PLLI2SDIVQ_MASK (31 << 0) /**< PLLI2SDIVQ mask. */ +#define STM32_PLLSAIDIVQ_MASK (31 << 8) /**< PLLSAIDIVQ mask. */ + +#define STM32_PLLSAIDIVR_MASK (3 << 16) /**< PLLSAIDIVR mask. */ +#define STM32_PLLSAIDIVR_DIV2 (0 << 16) /**< LCD_CLK is R divided by 2. */ +#define STM32_PLLSAIDIVR_DIV4 (1 << 16) /**< LCD_CLK is R divided by 4. */ +#define STM32_PLLSAIDIVR_DIV8 (2 << 16) /**< LCD_CLK is R divided by 8. */ +#define STM32_PLLSAIDIVR_DIV16 (3 << 16) /**< LCD_CLK is R divided by 16.*/ +#define STM32_PLLSAIDIVR_OFF 0xFFFFFFFFU /**< LCD CLK is not required. */ + +#define STM32_SAI1SEL_MASK (3 << 20) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_PLLSAI (0 << 20) /**< SAI1 source is PLLSAI. */ +#define STM32_SAI1SEL_PLLI2S (1 << 20) /**< SAI1 source is PLLI2S. */ +#define STM32_SAI1SEL_PLLR (2 << 20) /**< SAI1 source is PLLR. */ +#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ + +#define STM32_SAI2SEL_MASK (3 << 22) /**< SAI2SEL mask. */ +#define STM32_SAI2SEL_PLLSAI (0 << 22) /**< SAI2 source is PLLSAI. */ +#define STM32_SAI2SEL_PLLI2S (1 << 22) /**< SAI2 source is PLLI2S. */ +#define STM32_SAI2SEL_PLLR (2 << 22) /**< SAI2 source is PLLR. */ +#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ + +#define STM32_TIMPRE_MASK (1 << 24) /**< TIMPRE mask. */ +#define STM32_TIMPRE_PCLK (0 << 24) /**< TIM clocks from PCLKx. */ +#define STM32_TIMPRE_HCLK (1 << 24) /**< TIM clocks from HCLK. */ + +#define STM32_I2S1SEL_MASK (3 << 25) /**< I2S1SEL mask. */ +#define STM32_I2S1SEL_PLLR (0 << 25) /**< I2S1 source is PLLR. */ +#define STM32_I2S1SEL_AFIN (1 << 25) /**< I2S1 source is AF Input. */ +#define STM32_I2S1SEL_MCO1 (2 << 25) /**< I2S1 source is MCO1. */ +#define STM32_I2S1SEL_OFF 0xFFFFFFFFU /**< I2S1 clock is not required.*/ + +#define STM32_I2S2SEL_MASK (3 << 27) /**< I2S2SEL mask. */ +#define STM32_I2S2SEL_PLLR (0 << 27) /**< I2S2 source is PLLR. */ +#define STM32_I2S2SEL_AFIN (1 << 27) /**< I2S2 source is AF Input. */ +#define STM32_I2S2SEL_MCO1 (2 << 27) /**< I2S2 source is MCO1. */ +#define STM32_I2S2SEL_OFF 0xFFFFFFFFU /**< I2S2 clock is not required.*/ + +#define STM32_DSISEL_MASK (1 << 28) /**< DSISEL mask. */ +#define STM32_DSISEL_PHY (0 << 28) /**< DSI source is DSI-PSY. */ +#define STM32_DSISEL_PLLR (1 << 28) /**< DSI source is PLLR. */ +/** @} */ + +/** + * @name RCC_DCKCFGR2 register bits definitions + * @{ + */ +#define STM32_I2C1SEL_MASK (3 << 22) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK1 (0 << 22) /**< I2C1 source is APB/PCLK1. */ +#define STM32_I2C1SEL_SYSCLK (1 << 22) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI (2 << 22) /**< I2C1 source is HSI. */ + +#define STM32_CECSEL_MASK (1 << 26) /**< CECSEL mask. */ +#define STM32_CECSEL_LSE (0 << 26) /**< CEC source is LSE. */ +#define STM32_CECSEL_HSIDIV488 (1 << 26) /**< CEC source is HSI/488. */ + +#define STM32_CK48MSEL_MASK (1 << 27) /**< CK48MSEL mask. */ +#define STM32_CK48MSEL_PLL (0 << 27) /**< PLL48CLK source is PLL. */ +#define STM32_CK48MSEL_PLLSAI (1 << 27) /**< PLL48CLK source is PLLSAI. */ +#define STM32_CK48MSEL_PLLALT (1 << 27) /**< Alias. */ + +#define STM32_SDMMCSEL_MASK (1 << 28) /**< SDMMCSEL mask. */ +#define STM32_SDMMCSEL_PLL48CLK (0 << 28) /**< SDMMC source is PLL48CLK. */ +#define STM32_SDMMCSEL_SYSCLK (1 << 28) /**< SDMMC source is SYSCLK. */ + +#define STM32_SPDIFSEL_MASK (1 << 29) /**< SPDIFSEL mask. */ +#define STM32_SPDIFSEL_PLLI2S (0 << 29) /**< SPDIF source is PLLI2S. */ +#define STM32_SPDIFSEL_PLL (1 << 29) /**< SPDIF source is PLL. */ + +#define STM32_LPTIM1SEL_MASK (3 << 30) /**< LPTIM1 mask. */ +#define STM32_LPTIM1SEL_APB (0 << 30) /**< LPTIM1 source is APB. */ +#define STM32_LPTIM1SEL_HSI (1 << 30) /**< LPTIM1 source is HSI. */ +#define STM32_LPTIM1SEL_LSI (2 << 30) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_LSE (3 << 30) /**< LPTIM1 source is LSE. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables the backup RAM regulator. + */ +#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__) +#define STM32_BKPRAM_ENABLE FALSE +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief USB/SDIO clock setting. + */ +#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) +#define STM32_CLOCK48_REQUIRED TRUE +#endif + +/** + * @brief Main clock source selection. + * @note If the selected clock source is not the PLL then the PLL is not + * initialized and started. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +#if defined(STM32F4XX) || defined(__DOXYGEN__) +/** + * @brief Clock source for the PLLs. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 8 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 192..432. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 336 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 2 +#endif + +/** + * @brief PLLQ multiplier value. + * @note The allowed values are 2..15. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 7 +#endif + +/** + * @brief PLLR divider value. + * @note The allowed values are 2..7. + * @note The default value is calculated for a 96MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLR_VALUE 4 +#endif + +#else /* !defined(STM32F4XX) */ +/** + * @brief Clock source for the PLLs. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 8 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 192..432. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 240 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 2 +#endif + +/** + * @brief PLLQ multiplier value. + * @note The allowed values are 2..15. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 5 +#endif +#endif /* !defined(STM32F4XX) */ + +/** + * @brief I2S clock source (post-PLL). + * @note Not all devices have this setting, it is alternative to + * @p STM32_PLLI2SSRC. + */ +#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__) +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#endif + +/** + * @brief I2S clock source (pre-PLL). + * @note Not all devices have this setting, it is alternative to + * @p STM32_I2SSRC. + */ +#if !defined(STM32_PLLI2SSRC) || defined(__DOXYGEN__) +#define STM32_PLLI2SSRC STM32_PLLI2SSRC_CKIN +#endif + +/** + * @brief I2S external clock value, zero if not present. + * @note Not all devices have this setting. + */ +#if !defined(STM32_I2SCKIN_VALUE) || defined(__DOXYGEN__) +#define STM32_I2SCKIN_VALUE 0 +#endif + +/** + * @brief PLLI2SN multiplier value. + * @note The allowed values are 192..432, except for + * STM32F446 where values are 50...432. + * @note The default value is calculated for a 96MHz I2S clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SN_VALUE 192 +#endif + +/** + * @brief PLLI2SM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 96MHz I2S clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLI2SM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SM_VALUE 4 +#endif + +/** + * @brief PLLI2SR divider value. + * @note The allowed values are 2..7. + * @note The default value is calculated for a 96MHz I2S clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SR_VALUE 4 +#endif + +/** + * @brief PLLI2SP divider value. + * @note The allowed values are 2, 4, 6 and 8. + */ +#if !defined(STM32_PLLI2SP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SP_VALUE 4 +#endif + +/** + * @brief PLLI2SQ divider value. + * @note The allowed values are 2..15. + */ +#if !defined(STM32_PLLI2SQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SQ_VALUE 4 +#endif + +/** + * @brief PLLI2SDIVQ divider value (SAI clock divider). + * @note The allowed values are 1..32. + */ +#if !defined(STM32_PLLI2SDIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SDIVQ_VALUE 1 +#endif + +/** + * @brief PLLSAIM value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 96MHz SAI clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSAIM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIM_VALUE 4 +#endif + +/** + * @brief PLLSAIN value. + * @note The allowed values are 50..432. + * @note The default value is calculated for a 96MHz SAI clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSAIN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIN_VALUE 192 +#endif + +/** + * @brief PLLSAIM value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 96MHz SAI clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSAIM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIM_VALUE 4 +#endif + +/** + * @brief PLLSAIR value. + * @note The allowed values are 2..7. + */ +#if !defined(STM32_PLLSAIR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIR_VALUE 4 +#endif + +/** + * @brief PLLSAIP divider value. + * @note The allowed values are 2, 4, 6 and 8. + */ +#if !defined(STM32_PLLSAIP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIP_VALUE 8 +#endif + +/** + * @brief PLLSAIQ value. + * @note The allowed values are 2..15. + */ +#if !defined(STM32_PLLSAIQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIQ_VALUE 4 +#endif + +/** + * @brief PLLSAIDIVR divider value (SAI clock divider). + */ +#if !defined(STM32_PLLSAIDIVR) || defined(__DOXYGEN__) +#define STM32_PLLSAIDIVR STM32_PLLSAIDIVR_OFF +#endif + +/** + * @brief PLLSAIDIVQ divider value (LCD clock divider). + * @note The allowed values are 1..32. + */ +#if !defined(STM32_PLLSAIDIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIDIVQ_VALUE 1 +#endif + +/** + * @brief SAI1SEL value (SAI1 clock source). + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#endif + +/** + * @brief SAI2SEL value (SAI2 clock source). + */ +#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#endif + +/** + * @brief TIM prescaler clock source. + */ +#if !defined(STM32_TIMPRE) || defined(__DOXYGEN__) +#define STM32_TIMPRE STM32_TIMPRE_PCLK +#endif + +/** + * @brief PLL48CLK clock source. + */ +#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#endif + +/** + * @brief AHB prescaler value. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief RTC HSE prescaler value. + */ +#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) +#define STM32_RTCPRE_VALUE 8 +#endif + +/** + * @brief MCO1 clock source value. + * @note The default value outputs HSI clock on MCO1 pin. + */ +#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#endif + +/** + * @brief MCO1 prescaler value. + * @note The default value outputs HSI clock on MCO1 pin. + */ +#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#endif + +/** + * @brief MCO2 clock source value. + * @note The default value outputs SYSCLK / 5 on MCO2 pin. + */ +#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#endif + +/** + * @brief MCO2 prescaler value. + * @note The default value outputs SYSCLK / 5 on MCO2 pin. + */ +#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if defined(STM32F4XX) || defined(__DOXYGEN__) +/* + * Configuration-related checks. + */ +#if !defined(STM32F4xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined" +#endif + +#if defined(STM32F405xx) && !defined(STM32F405_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F405_MCUCONF not defined" +#endif + +#if defined(STM32F415xx) && !defined(STM32F415_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F415_MCUCONF not defined" +#endif + +#if defined(STM32F407xx) && !defined(STM32F407_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F407_MCUCONF not defined" +#endif + +#if defined(STM32F417xx) && !defined(STM32F417_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F417_MCUCONF not defined" +#endif + +#else /* !defined(STM32F4XX) */ +/* + * Configuration-related checks. + */ +#if !defined(STM32F2xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F2xx_MCUCONF not defined" +#endif +#endif /* !defined(STM32F4XX) */ + +/** + * @name Maximum frequency thresholds, wait states and + * parallelism for flash access. + * @{ + */ +#if defined(STM32F429_439xx) || defined(STM32F427_437xx) || \ + defined(STM32F40_41xxx) || defined(STM32F446xx) || \ + defined(STM32F469_479xx) || defined(__DOXYGEN__) +#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 60000000 +#define STM32_2WS_THRESHOLD 90000000 +#define STM32_3WS_THRESHOLD 120000000 +#define STM32_4WS_THRESHOLD 150000000 +#define STM32_5WS_THRESHOLD 180000000 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 2 +#elif (STM32_VDD >= 240) && (STM32_VDD < 270) +#define STM32_0WS_THRESHOLD 24000000 +#define STM32_1WS_THRESHOLD 48000000 +#define STM32_2WS_THRESHOLD 72000000 +#define STM32_3WS_THRESHOLD 96000000 +#define STM32_4WS_THRESHOLD 120000000 +#define STM32_5WS_THRESHOLD 144000000 +#define STM32_6WS_THRESHOLD 168000000 +#define STM32_7WS_THRESHOLD 180000000 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 210) && (STM32_VDD < 240) +#define STM32_0WS_THRESHOLD 22000000 +#define STM32_1WS_THRESHOLD 44000000 +#define STM32_2WS_THRESHOLD 66000000 +#define STM32_3WS_THRESHOLD 88000000 +#define STM32_4WS_THRESHOLD 110000000 +#define STM32_5WS_THRESHOLD 132000000 +#define STM32_6WS_THRESHOLD 154000000 +#define STM32_7WS_THRESHOLD 176000000 +#define STM32_8WS_THRESHOLD 180000000 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 180) && (STM32_VDD < 210) +#define STM32_0WS_THRESHOLD 20000000 +#define STM32_1WS_THRESHOLD 40000000 +#define STM32_2WS_THRESHOLD 60000000 +#define STM32_3WS_THRESHOLD 80000000 +#define STM32_4WS_THRESHOLD 100000000 +#define STM32_5WS_THRESHOLD 120000000 +#define STM32_6WS_THRESHOLD 140000000 +#define STM32_7WS_THRESHOLD 168000000 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 0 +#else +#error "invalid VDD voltage specified" +#endif + +#elif defined(STM32F412xx) +#if (STM32_VDD >= 270) && (STM32_VDD <= 360) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 64000000 +#define STM32_2WS_THRESHOLD 90000000 +#define STM32_3WS_THRESHOLD 100000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 2 +#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 100000000 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#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 100000000 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 170) && (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 100000000 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 0 +#else +#error "invalid VDD voltage specified" +#endif + +#elif defined(STM32F410xx) || defined(STM32F411xx) +#if (STM32_VDD >= 270) && (STM32_VDD <= 360) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 64000000 +#define STM32_2WS_THRESHOLD 90000000 +#define STM32_3WS_THRESHOLD 100000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 2 +#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 100000000 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#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 100000000 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 171) && (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 100000000 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 0 + +#else +#error "invalid VDD voltage specified" +#endif + +#elif defined(STM32F401xx) +#if (STM32_VDD >= 270) && (STM32_VDD <= 360) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 60000000 +#define STM32_2WS_THRESHOLD 84000000 +#define STM32_3WS_THRESHOLD 0 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 2 + +#elif (STM32_VDD >= 240) && (STM32_VDD < 270) +#define STM32_0WS_THRESHOLD 24000000 +#define STM32_1WS_THRESHOLD 48000000 +#define STM32_2WS_THRESHOLD 72000000 +#define STM32_3WS_THRESHOLD 84000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 + +#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 84000000 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 + +#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 84000000 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 0 + +#else +#error "invalid VDD voltage specified" +#endif + +#else /* STM32F2XX */ +#if (STM32_VDD >= 270) && (STM32_VDD <= 360) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 60000000 +#define STM32_2WS_THRESHOLD 90000000 +#define STM32_3WS_THRESHOLD 120000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 2 +#elif (STM32_VDD >= 240) && (STM32_VDD < 270) +#define STM32_0WS_THRESHOLD 24000000 +#define STM32_1WS_THRESHOLD 48000000 +#define STM32_2WS_THRESHOLD 72000000 +#define STM32_3WS_THRESHOLD 96000000 +#define STM32_4WS_THRESHOLD 120000000 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 210) && (STM32_VDD < 240) +#define STM32_0WS_THRESHOLD 18000000 +#define STM32_1WS_THRESHOLD 36000000 +#define STM32_2WS_THRESHOLD 54000000 +#define STM32_3WS_THRESHOLD 72000000 +#define STM32_4WS_THRESHOLD 90000000 +#define STM32_5WS_THRESHOLD 108000000 +#define STM32_6WS_THRESHOLD 120000000 +#define STM32_7WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 180) && (STM32_VDD < 210) +#define STM32_0WS_THRESHOLD 16000000 +#define STM32_1WS_THRESHOLD 32000000 +#define STM32_2WS_THRESHOLD 48000000 +#define STM32_3WS_THRESHOLD 64000000 +#define STM32_4WS_THRESHOLD 80000000 +#define STM32_5WS_THRESHOLD 96000000 +#define STM32_6WS_THRESHOLD 112000000 +#define STM32_7WS_THRESHOLD 120000000 +#define STM32_FLASH_PSIZE 0 + +#else +#error "invalid VDD voltage specified" +#endif +#endif /* STM32F2XX */ +/** @} */ + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_I2SSRC" +#endif + +#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_I2SSRC" +#endif + +#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SAI1SEL" +#endif + +#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SAI2SEL" +#endif +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#else /* STM32_HSECLK != 0 */ +#if defined(STM32_HSE_BYPASS) +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_BYP_MAX)" +#endif +#else /* !defined(STM32_HSE_BYPASS) */ +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif +#endif /* !defined(STM32_HSE_BYPASS) */ +#endif /* STM32_HSECLK != 0 */ +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ + ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_I2SSRC" +#endif + +#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_PLLI2SSRC" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief Clock frequency feeding PLLs. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSRCCLK STM32_HSECLK +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLSRCCLK STM32_HSICLK +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/** + * @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 PLL input clock frequency. + */ +#define STM32_PLLCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) + +/* + * PLLs input frequency range check. + */ +#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_CLOCK48_REQUIRED && \ + STM32_HAS_RCC_CK48MSEL && \ + (STM32_CK48MSEL == STM32_CK48MSEL_PLL)) || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ + (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 6) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLP STM32_PLLP_DIV2 +#elif STM32_PLLP_VALUE == 4 +#define STM32_PLLP STM32_PLLP_DIV4 +#elif STM32_PLLP_VALUE == 6 +#define STM32_PLLP STM32_PLLP_DIV6 +#elif STM32_PLLP_VALUE == 8 +#define STM32_PLLP STM32_PLLP_DIV8 +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +#if defined(STM32F4XX) || defined(__DOXYGEN__) +/** + * @brief STM32_PLLR field. + */ +#if ((STM32_PLLR_VALUE >= 2) && (STM32_PLLR_VALUE <= 7)) || \ + defined(__DOXYGEN__) +#define STM32_PLLR (STM32_PLLR_VALUE << 28) +#else +#error "invalid STM32_PLLR_VALUE value specified" +#endif +#else /* !defined(STM32F4XX) */ +#define STM32_PLLR 0 +#endif /* !defined(STM32F4XX) */ + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) + +/* + * PLL output frequency range check. + */ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/* Calculating VOS settings, it is different for each sub-platform.*/ +#if defined(STM32F429_439xx) || defined(STM32F427_437xx) || \ + defined(STM32F446xx) || defined(STM32F469_479xx) || \ + defined(__DOXYGEN__) +#if STM32_SYSCLK <= 120000000 +#define STM32_VOS STM32_VOS_SCALE3 +#define STM32_OVERDRIVE_REQUIRED FALSE +#elif STM32_SYSCLK <= 144000000 +#define STM32_VOS STM32_VOS_SCALE2 +#define STM32_OVERDRIVE_REQUIRED FALSE +#elif STM32_SYSCLK <= 168000000 +#define STM32_VOS STM32_VOS_SCALE1 +#define STM32_OVERDRIVE_REQUIRED FALSE +#else +#define STM32_VOS STM32_VOS_SCALE1 +#define STM32_OVERDRIVE_REQUIRED TRUE +#endif + +#elif defined(STM32F40_41xxx) +#if STM32_SYSCLK <= 144000000 +#define STM32_VOS STM32_VOS_SCALE2 +#else +#define STM32_VOS STM32_VOS_SCALE1 +#endif +#define STM32_OVERDRIVE_REQUIRED FALSE + +#elif defined(STM32F401xx) +#if STM32_SYSCLK <= 60000000 +#define STM32_VOS STM32_VOS_SCALE3 +#else +#define STM32_VOS STM32_VOS_SCALE2 +#endif +#define STM32_OVERDRIVE_REQUIRED FALSE + +#elif defined(STM32F410xx) || defined(STM32F411xx) || \ + defined(STM32F412xx) +#if STM32_SYSCLK <= 64000000 +#define STM32_VOS STM32_VOS_SCALE3 +#elif STM32_SYSCLK <= 84000000 +#define STM32_VOS STM32_VOS_SCALE2 +#else +#define STM32_VOS STM32_VOS_SCALE1 +#endif +#define STM32_OVERDRIVE_REQUIRED FALSE + +#else /* STM32F2XX */ +#define STM32_OVERDRIVE_REQUIRED FALSE +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/* + * PLLI2S enable check. + */ +#if (STM32_HAS_RCC_PLLI2S && \ + (STM32_CLOCK48_REQUIRED && \ + (STM32_HAS_RCC_CK48MSEL && \ + STM32_RCC_CK48MSEL_USES_I2S && \ + (STM32_CK48MSEL == STM32_CK48MSEL_PLLALT)) || \ + (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S))) || \ + defined(__DOXYGEN__) + +/** + * @brief PLLI2S activation flag. + */ +#define STM32_ACTIVATE_PLLI2S TRUE +#else +#define STM32_ACTIVATE_PLLI2S FALSE +#endif + +/** + * @brief STM32_PLLI2SM field. + */ +#if ((STM32_PLLI2SM_VALUE >= 2) && (STM32_PLLI2SM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SM (STM32_PLLI2SM_VALUE << 0) +#else +#error "invalid STM32_PLLI2SM_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SN field. + */ +#if ((STM32_PLLI2SN_VALUE >= 50) && (STM32_PLLI2SN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) +#else +#error "invalid STM32_PLLI2SN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SP field. + */ +#if (STM32_PLLI2SP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLI2SP STM32_PLLI2SP_DIV2 +#elif STM32_PLLI2SP_VALUE == 4 +#define STM32_PLLI2SP STM32_PLLI2SP_DIV4 +#elif STM32_PLLI2SP_VALUE == 6 +#define STM32_PLLI2SP STM32_PLLI2SP_DIV6 +#elif STM32_PLLI2SP_VALUE == 8 +#define STM32_PLLI2SP STM32_PLLI2SP_DIV8 +#else +#error "invalid STM32_PLLI2SP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SQ field. + */ +#if ((STM32_PLLI2SQ_VALUE >= 2) && (STM32_PLLI2SQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SQ (STM32_PLLI2SQ_VALUE << 24) +#else +#error "invalid STM32_PLLI2SQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SDIVQ field. + */ +#if ((STM32_PLLI2SDIVQ_VALUE >= 1) && (STM32_PLLI2SDIVQ_VALUE <= 32)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SDIVQ ((STM32_PLLI2SQ_VALUE - 1) << 0) +#else +#error "invalid STM32_PLLI2SDIVQ_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 PLLI2S input clock frequency. + */ +#if STM32_HAS_RCC_I2SPLLSRC || defined(__DOXYGEN__) +#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLI2SM_VALUE) +#elif STM32_PLLI2SSRC == STM32_PLLI2SSRC_CKIN +#define STM32_PLLI2SCLKIN (STM32_I2SCKIN_VALUE / STM32_PLLI2SM_VALUE) +#else +#error "invalid STM32_PLLI2SSRC value specified" +#endif +#else +#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) +#endif + +/** + * @brief PLLI2S VCO frequency. + */ +#define STM32_PLLI2SVCO (STM32_PLLI2SCLKIN * 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 P output clock frequency. + */ +#define STM32_PLLI2S_P_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SP_VALUE) + +/** + * @brief PLLI2S Q output clock frequency. + */ +#define STM32_PLLI2S_Q_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SQ_VALUE) + +/** + * @brief PLLI2S R output clock frequency. + */ +#define STM32_PLLI2S_R_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) + +/* + * PLLSAI enable check. + */ +#if (STM32_HAS_RCC_PLLSAI && \ + (STM32_CLOCK48_REQUIRED && \ + (STM32_HAS_RCC_CK48MSEL && \ + !STM32_RCC_CK48MSEL_USES_I2S && \ + (STM32_CK48MSEL == STM32_CK48MSEL_PLLALT)) || \ + (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI))) || \ + (STM32_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF) || \ + defined(__DOXYGEN__) +/** + * @brief PLLSAI activation flag. + */ +#define STM32_ACTIVATE_PLLSAI TRUE +#else +#define STM32_ACTIVATE_PLLSAI FALSE +#endif + +/** + * @brief STM32_PLLSAIM field. + */ +#if ((STM32_PLLSAIM_VALUE >= 2) && (STM32_PLLSAIM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIM (STM32_PLLSAIM_VALUE << 0) +#else +#error "invalid STM32_PLLSAIM_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIN field. + */ +#if ((STM32_PLLSAIN_VALUE >= 49) && (STM32_PLLSAIN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIN (STM32_PLLSAIN_VALUE << 6) +#else +#error "invalid STM32_PLLSAIN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIQ field. + */ +#if ((STM32_PLLSAIQ_VALUE >= 2) && (STM32_PLLSAIQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIQ (STM32_PLLSAIQ_VALUE << 24) +#else +#error "invalid STM32_PLLSAIQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIDIVQ_VALUE field. + */ +#if ((STM32_PLLSAIDIVQ_VALUE >= 1) && (STM32_PLLSAIDIVQ_VALUE <= 32)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIDIVQ ((STM32_PLLSAIDIVQ_VALUE - 1) << 8) +#else +#error "invalid STM32_PLLSAIDIVQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIR field. + */ +#if ((STM32_PLLSAIR_VALUE >= 2) && (STM32_PLLSAIR_VALUE <= 7)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIR (STM32_PLLSAIR_VALUE << 28) +#else +#error "invalid STM32_PLLSAIR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIP field. + */ + +#if (STM32_PLLSAIP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAIP STM32_PLLSAIP_DIV2 + +#elif STM32_PLLSAIP_VALUE == 4 +#define STM32_PLLSAIP STM32_PLLSAIP_DIV4 + +#elif STM32_PLLSAIP_VALUE == 6 +#define STM32_PLLSAIP STM32_PLLSAIP_DIV6 + +#elif STM32_PLLSAIP_VALUE == 8 +#define STM32_PLLSAIP STM32_PLLSAIP_DIV8 + +#else +#error "invalid STM32_PLLSAIP_VALUE value specified" +#endif + +/** + * @brief PLLSAI input clock frequency. + */ +#if defined(STM32F446xx) +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSAICLKIN (STM32_HSECLK / STM32_PLLSAIM_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLSAICLKIN (STM32_HSICLK / STM32_PLLSAIM_VALUE) +#else +#error "invalid STM32_PLLSRC value specified" +#endif +#else /* !defined(STM32F446xx) */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSAICLKIN (STM32_HSECLK / STM32_PLLM_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLSAICLKIN (STM32_HSICLK / STM32_PLLM_VALUE) +#else +#error "invalid STM32_PLLSRC value specified" +#endif +#endif /* defined(STM32F446xx) */ + +/** + * @brief PLLSAI VCO frequency. + */ +#define STM32_PLLSAIVCO (STM32_PLLSAICLKIN * STM32_PLLSAIN_VALUE) + +/* + * PLLSAI VCO frequency range check. + */ +#if (STM32_PLLSAIVCO < STM32_PLLVCO_MIN) || \ + (STM32_PLLSAIVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLSAIVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI P output clock frequency. + */ +#define STM32_PLLSAI_P_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIP_VALUE) + +/** + * @brief PLLSAI Q output clock frequency. + */ +#define STM32_PLLSAI_Q_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIQ_VALUE) + +/** + * @brief PLLSAI R output clock frequency. + */ +#define STM32_PLLSAI_R_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIR_VALUE) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_TYPE1_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld_type2.h b/os/hal/ports/STM32/STM32F4xx/hal_lld_type2.h index 6967d450e2..789f0bc570 100644 --- a/os/hal/ports/STM32/STM32F4xx/hal_lld_type2.h +++ b/os/hal/ports/STM32/STM32F4xx/hal_lld_type2.h @@ -1,1231 +1,1239 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/hal_lld_type2.h - * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. - * @pre This module requires the following macros to be defined in the - * @p board.h file: - * - STM32_LSECLK. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * - STM32_VDD (as hundredths of Volt). - * . - * One of the following macros must also be defined: - * - STM32F413xx for High-performance STM32F4 devices of Access line. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_TYPE2_H -#define HAL_LLD_TYPE2_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Defines the support for realtime counters in the HAL. - */ -#define HAL_IMPLEMENTS_COUNTERS TRUE - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32F413xx) -#define PLATFORM_NAME "STM32F413 High Performance with DSP and FPU" - -#else -#error "STM32F2xx/F4xx device not specified" -#endif -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ - -#if defined(STM32F413xx) || defined(__DOXYGEN__) -/** - * @brief Absolute maximum system clock. - */ -#define STM32_SYSCLK_MAX 100000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 26000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 50000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 1000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency using an external source. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 2100000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 950000 - -/** - * @brief Maximum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MAX 432000000 - -/** - * @brief Minimum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MIN 100000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 100000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 24000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 50000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 100000000 - -/** - * @brief Maximum SPI/I2S clock frequency. - */ -#define STM32_SPII2S_MAX 50000000 -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 16000000 /**< High speed internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_VOS_SCALE3 0x00004000 -#define STM32_VOS_SCALE2 0x00008000 -#define STM32_VOS_SCALE1 0x0000C000 -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ -#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ -#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ -#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ -#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW mask. */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ -#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ -#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ - -#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ - -#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ -#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ -#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ - -#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ -#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ -#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ -#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ -#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ -#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ - -#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ -#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ -#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ -#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ -#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ -#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ - -#define STM32_MCO2SEL_MASK (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. */ - -/** - * @name RCC_PLLI2SCFGR register bits definitions - * @{ - */ -#define STM32_PLLI2SM_MASK (31 << 0) /**< PLLI2SM mask. */ -#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ -#define STM32_PLLI2SSRC_MASK (1 << 22) /**< PLLI2SSRC mask. */ -#define STM32_PLLI2SSRC_PLLSRC (0 << 22) /**< PLLI2SSRC is selected PLL - source. */ -#define STM32_PLLI2SSRC_CKIN (1 << 22) /**< PLLI2SSRC is I2S_CKIN. */ -#define STM32_PLLI2SQ_MASK (15 << 24) /**< PLLI2SQ mask. */ -#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ -/** @} */ - -/** - * @name RCC_DCKCFGR register bits definitions - * @{ - */ -#define STM32_PLLI2SDIVR_MASK (31 << 0) /**< PLLI2SDIVR mask. */ -#define STM32_PLLDIVR_MASK (31 << 8) /**< PLLDIVR mask. */ - -#define STM32_SAI1SEL_MASK (3 << 20) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_PLLSAI (0 << 20) /**< SAI1 source is PLLSAI. */ -#define STM32_SAI1SEL_PLLI2S (1 << 20) /**< SAI1 source is PLLI2S. */ -#define STM32_SAI1SEL_PLLR (2 << 20) /**< SAI1 source is PLLR. */ -#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ - -#define STM32_SAI2SEL_MASK (3 << 22) /**< SAI2SEL mask. */ -#define STM32_SAI2SEL_PLLSAI (0 << 22) /**< SAI2 source is PLLSAI. */ -#define STM32_SAI2SEL_PLLI2S (1 << 22) /**< SAI2 source is PLLI2S. */ -#define STM32_SAI2SEL_PLLR (2 << 22) /**< SAI2 source is PLLR. */ -#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ - -#define STM32_TIMPRE_MASK (1 << 24) /**< TIMPRE mask. */ -#define STM32_TIMPRE_PCLK (0 << 24) /**< TIM clocks from PCLKx. */ -#define STM32_TIMPRE_HCLK (1 << 24) /**< TIM clocks from HCLK. */ - -#define STM32_I2S1SEL_MASK (3 << 25) /**< I2S1SEL mask. */ -#define STM32_I2S1SEL_PLLR (0 << 25) /**< I2S1 source is PLLR. */ -#define STM32_I2S1SEL_AFIN (1 << 25) /**< I2S1 source is AF Input. */ -#define STM32_I2S1SEL_MCO1 (2 << 25) /**< I2S1 source is MCO1. */ -#define STM32_I2S1SEL_OFF 0xFFFFFFFFU /**< I2S1 clock is not required.*/ - -#define STM32_I2S2SEL_MASK (3 << 27) /**< I2S2SEL mask. */ -#define STM32_I2S2SEL_PLLR (0 << 27) /**< I2S2 source is PLLR. */ -#define STM32_I2S2SEL_AFIN (1 << 27) /**< I2S2 source is AF Input. */ -#define STM32_I2S2SEL_MCO1 (2 << 27) /**< I2S2 source is MCO1. */ -#define STM32_I2S2SEL_OFF 0xFFFFFFFFU /**< I2S2 clock is not required.*/ -/** @} */ - -/** - * @name RCC_DCKCFGR2 register bits definitions - * @{ - */ -#define STM32_I2CFMP1SEL_MASK (3 << 22) /**< I2CFMP1SEL mask. */ -#define STM32_I2CFMP1SEL_PCLK1 (0 << 22) /**< I2C1 source is APB/PCLK1. */ -#define STM32_I2CFMP1SEL_SYSCLK (1 << 22) /**< I2C1 source is SYSCLK. */ -#define STM32_I2CFMP1SEL_HSI (2 << 22) /**< I2C1 source is HSI. */ - -#define STM32_CK48MSEL_MASK (1 << 27) /**< CK48MSEL mask. */ -#define STM32_CK48MSEL_PLL (0 << 27) /**< PLL48CLK source is PLL. */ -#define STM32_CK48MSEL_PLLI2S (1 << 27) /**< PLL48CLK source is PLLI2S. */ -#define STM32_CK48MSEL_PLLALT (1 << 27) /**< Alias. */ - -#define STM32_SDIOSEL_MASK (1 << 28) /**< SDIOSEL mask. */ -#define STM32_SDIOSEL_PLL48CLK (0 << 28) /**< SDIO source is PLL48CLK. */ -#define STM32_SDIOSEL_SYSCLK (1 << 28) /**< SDIO source is SYSCLK. */ - -#define STM32_LPTIM1SEL_MASK (3 << 30) /**< LPTIM1 mask. */ -#define STM32_LPTIM1SEL_APB (0 << 30) /**< LPTIM1 source is APB. */ -#define STM32_LPTIM1SEL_HSI (1 << 30) /**< LPTIM1 source is HSI. */ -#define STM32_LPTIM1SEL_LSI (2 << 30) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_LSE (3 << 30) /**< LPTIM1 source is LSE. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables the backup RAM regulator. - */ -#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__) -#define STM32_BKPRAM_ENABLE FALSE -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief USB/SDIO clock setting. - */ -#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) -#define STM32_CLOCK48_REQUIRED TRUE -#endif - -/** - * @brief Main clock source selection. - * @note If the selected clock source is not the PLL then the PLL is not - * initialized and started. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLLs. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 8 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 192..432. - * @note The default value is calculated for a 96MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 384 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 96MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 4 -#endif - -/** - * @brief PLLQ multiplier value. - * @note The allowed values are 2..15. - * @note The default value is calculated for a 96MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 8 -#endif - -/** - * @brief AHB prescaler value. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief I2S clock source (pre-PLL). - */ -#if !defined(STM32_PLLI2SSRC) || defined(__DOXYGEN__) -#define STM32_PLLI2SSRC STM32_PLLI2SSRC_PLLSRC -#endif - -/** - * @brief I2S external clock value, zero if not present. - */ -#if !defined(STM32_I2SCKIN_VALUE) || defined(__DOXYGEN__) -#define STM32_I2SCKIN_VALUE 0 -#endif - -/** - * @brief PLLI2SM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 96MHz I2S clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLI2SM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SM_VALUE 8 -#endif - -/** - * @brief PLLI2SN multiplier value. - * @note The allowed values are 192..432, except for - * STM32F446 where values are 50...432. - * @note The default value is calculated for a 96MHz I2S clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SN_VALUE 192 -#endif - -/** - * @brief PLLI2SR divider value. - * @note The allowed values are 2..7. - * @note The default value is calculated for a 96MHz I2S clock - * output from an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SR_VALUE 4 -#endif - -/** - * @brief PLLI2SQ divider value. - * @note The allowed values are 2..15. - */ -#if !defined(STM32_PLLI2SQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SQ_VALUE 4 -#endif - -/** - * @brief PLLI2SDIVR divider value (SAI clock divider). - * @note The allowed values are 1..32. - */ -#if !defined(STM32_PLLI2SDIVR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SDIVR_VALUE 1 -#endif - -/** - * @brief PLLDIVR divider value (SAI clock divider). - * @note The allowed values are 1..32. - */ -#if !defined(STM32_PLLDIVR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLDIVR_VALUE 1 -#endif - -/** - * @brief SAI1SEL value (SAI1 clock source). - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#endif - -/** - * @brief SAI2SEL value (SAI2 clock source). - */ -#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#endif - -/** - * @brief TIM prescaler clock source. - */ -#if !defined(STM32_TIMPRE) || defined(__DOXYGEN__) -#define STM32_TIMPRE STM32_TIMPRE_PCLK -#endif - -/** - * @brief PLL48CLK clock source. - */ -#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) -#define STM32_CK48MSEL STM32_CK48MSEL_PLL -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief RTC HSE prescaler value. - */ -#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) -#define STM32_RTCPRE_VALUE 8 -#endif - -/** - * @brief MCO1 clock source value. - * @note The default value outputs HSI clock on MCO1 pin. - */ -#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#endif - -/** - * @brief MCO1 prescaler value. - * @note The default value outputs HSI clock on MCO1 pin. - */ -#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#endif - -/** - * @brief MCO2 clock source value. - * @note The default value outputs SYSCLK / 5 on MCO2 pin. - */ -#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#endif - -/** - * @brief MCO2 prescaler value. - * @note The default value outputs SYSCLK / 5 on MCO2 pin. - */ -#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F4xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined" -#endif - -#if defined(STM32F413xx) && !defined(STM32F413_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F413_MCUCONF not defined" -#endif - -/** - * @name Maximum frequency thresholds, wait states and - * parallelism for flash access. - * @{ - */ -#if defined(STM32F413xx) -#if (STM32_VDD >= 270) && (STM32_VDD <= 360) -#define STM32_0WS_THRESHOLD 25000000 -#define STM32_1WS_THRESHOLD 50000000 -#define STM32_2WS_THRESHOLD 75000000 -#define STM32_3WS_THRESHOLD 100000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 2 -#elif (STM32_VDD >= 240) && (STM32_VDD < 270) -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#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 100000000 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 1 -#elif (STM32_VDD >= 170) && (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 100000000 -#define STM32_7WS_THRESHOLD 0 -#define STM32_8WS_THRESHOLD 0 -#define STM32_FLASH_PSIZE 0 -#else -#error "invalid VDD voltage specified" -#endif -#define FLASH_SR_OPERR FLASH_SR_SOP -#endif /* defined(STM32F413xx) */ -/** @} */ - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_I2SSRC" -#endif - -#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SAI1SEL" -#endif - -#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SAI2SEL" -#endif -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#else /* STM32_HSECLK != 0 */ -#if defined(STM32_HSE_BYPASS) -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_BYP_MAX)" -#endif -#else /* !defined(STM32_HSE_BYPASS) */ -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif -#endif /* !defined(STM32_HSE_BYPASS) */ -#endif /* STM32_HSECLK != 0 */ -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ - ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_PLLI2SSRC" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief Clock frequency feeding PLLs. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSRCCLK STM32_HSECLK -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLSRCCLK STM32_HSICLK -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/** - * @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 PLL input clock frequency. - */ -#define STM32_PLLCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) - -/* - * PLLs input frequency range check. - */ -#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_CLOCK48_REQUIRED && \ - STM32_HAS_RCC_CK48MSEL && \ - (STM32_CK48MSEL == STM32_CK48MSEL_PLL)) || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ - (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 6) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLP STM32_PLLP_DIV2 -#elif STM32_PLLP_VALUE == 4 -#define STM32_PLLP STM32_PLLP_DIV4 -#elif STM32_PLLP_VALUE == 6 -#define STM32_PLLP STM32_PLLP_DIV6 -#elif STM32_PLLP_VALUE == 8 -#define STM32_PLLP STM32_PLLP_DIV8 -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLDIVR_VALUE field. - */ -#if ((STM32_PLLDIVR_VALUE >= 1) && (STM32_PLLDIVR_VALUE <= 32)) || \ - defined(__DOXYGEN__) -#define STM32_PLLDIVR ((STM32_PLLDIVR_VALUE - 1) << 8) -#else -#error "invalid STM32_PLLDIVR_VALUE value specified" -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) - -/* - * PLL output frequency range check. - */ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/* Calculating VOS settings, it is different for each sub-platform.*/ -#if defined(STM32F413xx) -#if STM32_SYSCLK <= 64000000 -#define STM32_VOS STM32_VOS_SCALE3 -#elif STM32_SYSCLK <= 84000000 -#define STM32_VOS STM32_VOS_SCALE2 -#else -#define STM32_VOS STM32_VOS_SCALE1 -#endif -#define STM32_OVERDRIVE_REQUIRED FALSE -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/* - * PLLI2S enable check. - */ -#if (STM32_HAS_RCC_PLLI2S && \ - (STM32_CLOCK48_REQUIRED && \ - (STM32_HAS_RCC_CK48MSEL && \ - STM32_RCC_CK48MSEL_USES_I2S && \ - (STM32_CK48MSEL == STM32_CK48MSEL_PLLI2S)) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S))) || \ - defined(__DOXYGEN__) - -/** - * @brief PLLI2S activation flag. - */ -#define STM32_ACTIVATE_PLLI2S TRUE -#else -#define STM32_ACTIVATE_PLLI2S FALSE -#endif - -/** - * @brief STM32_PLLI2SM field. - */ -#if ((STM32_PLLI2SM_VALUE >= 2) && (STM32_PLLI2SM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SM (STM32_PLLI2SM_VALUE << 0) -#else -#error "invalid STM32_PLLI2SM_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SN field. - */ -#if ((STM32_PLLI2SN_VALUE >= 50) && (STM32_PLLI2SN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) -#else -#error "invalid STM32_PLLI2SN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SQ field. - */ -#if ((STM32_PLLI2SQ_VALUE >= 2) && (STM32_PLLI2SQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SQ (STM32_PLLI2SQ_VALUE << 24) -#else -#error "invalid STM32_PLLI2SQ_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 STM32_PLLI2SDIVR field. - */ -#if ((STM32_PLLI2SDIVR_VALUE >= 1) && (STM32_PLLI2SDIVR_VALUE <= 32)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SDIVR ((STM32_PLLI2SR_VALUE - 1) << 0) -#else -#error "invalid STM32_PLLI2SDIVQ_VALUE value specified" -#endif - -/** - * @brief PLLI2S input clock frequency. - */ -#if STM32_HAS_RCC_I2SPLLSRC || defined(__DOXYGEN__) -#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLI2SM_VALUE) -#elif STM32_PLLI2SSRC == STM32_PLLI2SSRC_CKIN -#define STM32_PLLI2SCLKIN (STM32_I2SCKIN_VALUE / STM32_PLLI2SM_VALUE) -#else -#error "invalid STM32_PLLI2SSRC value specified" -#endif -#else -#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) -#endif - -/** - * @brief PLLI2S VCO frequency. - */ -#define STM32_PLLI2SVCO (STM32_PLLI2SCLKIN * 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 Q output clock frequency. - */ -#define STM32_PLLI2S_Q_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SQ_VALUE) - -/** - * @brief PLLI2S R output clock frequency. - */ -#define STM32_PLLI2S_R_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) - -/** - * @brief PLLI2SP enable bit. - * @note Always 0, there is no PLLI2SP. - */ -#define STM32_PLLI2SP 0 - -/** - * @brief PLLSAI activation flag. - * @note Always FALSE, there is no PLLSAI. - */ -#define STM32_ACTIVATE_PLLSAI FALSE - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_TYPE2_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/hal_lld_type2.h + * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - STM32_LSECLK. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * - STM32_VDD (as hundredths of Volt). + * . + * One of the following macros must also be defined: + * - STM32F413xx for High-performance STM32F4 devices of Access line. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_TYPE2_H +#define HAL_LLD_TYPE2_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +#define HAL_IMPLEMENTS_COUNTERS TRUE + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32F413xx) +#define PLATFORM_NAME "STM32F413 High Performance with DSP and FPU" + +#else +#error "STM32F2xx/F4xx device not specified" +#endif +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ + +#if defined(STM32F413xx) || defined(__DOXYGEN__) +/** + * @brief Absolute maximum system clock. + */ +#define STM32_SYSCLK_MAX 100000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 26000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 50000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency using an external source. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 2100000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 950000 + +/** + * @brief Maximum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MAX 432000000 + +/** + * @brief Minimum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MIN 100000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 100000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 24000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 50000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 100000000 + +/** + * @brief Maximum SPI/I2S clock frequency. + */ +#define STM32_SPII2S_MAX 50000000 +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 16000000 /**< High speed internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_VOS_SCALE3 0x00004000 +#define STM32_VOS_SCALE2 0x00008000 +#define STM32_VOS_SCALE1 0x0000C000 +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ +#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ +#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ +#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ +#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW mask. */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ +#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ +#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ + +#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ + +#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ +#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ +#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ + +#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ +#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ +#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ +#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ +#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ +#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ + +#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ +#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ +#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ +#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ +#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ +#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ + +#define STM32_MCO2SEL_MASK (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. */ + +/** + * @name RCC_PLLI2SCFGR register bits definitions + * @{ + */ +#define STM32_PLLI2SM_MASK (31 << 0) /**< PLLI2SM mask. */ +#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ +#define STM32_PLLI2SSRC_MASK (1 << 22) /**< PLLI2SSRC mask. */ +#define STM32_PLLI2SSRC_PLLSRC (0 << 22) /**< PLLI2SSRC is selected PLL + source. */ +#define STM32_PLLI2SSRC_CKIN (1 << 22) /**< PLLI2SSRC is I2S_CKIN. */ +#define STM32_PLLI2SQ_MASK (15 << 24) /**< PLLI2SQ mask. */ +#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ +/** @} */ + +/** + * @name RCC_DCKCFGR register bits definitions + * @{ + */ +#define STM32_PLLI2SDIVR_MASK (31 << 0) /**< PLLI2SDIVR mask. */ +#define STM32_PLLDIVR_MASK (31 << 8) /**< PLLDIVR mask. */ + +#define STM32_SAI1SEL_MASK (3 << 20) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_PLLSAI (0 << 20) /**< SAI1 source is PLLSAI. */ +#define STM32_SAI1SEL_PLLI2S (1 << 20) /**< SAI1 source is PLLI2S. */ +#define STM32_SAI1SEL_PLLR (2 << 20) /**< SAI1 source is PLLR. */ +#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ + +#define STM32_SAI2SEL_MASK (3 << 22) /**< SAI2SEL mask. */ +#define STM32_SAI2SEL_PLLSAI (0 << 22) /**< SAI2 source is PLLSAI. */ +#define STM32_SAI2SEL_PLLI2S (1 << 22) /**< SAI2 source is PLLI2S. */ +#define STM32_SAI2SEL_PLLR (2 << 22) /**< SAI2 source is PLLR. */ +#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ + +#define STM32_TIMPRE_MASK (1 << 24) /**< TIMPRE mask. */ +#define STM32_TIMPRE_PCLK (0 << 24) /**< TIM clocks from PCLKx. */ +#define STM32_TIMPRE_HCLK (1 << 24) /**< TIM clocks from HCLK. */ + +#define STM32_I2S1SEL_MASK (3 << 25) /**< I2S1SEL mask. */ +#define STM32_I2S1SEL_PLLR (0 << 25) /**< I2S1 source is PLLR. */ +#define STM32_I2S1SEL_AFIN (1 << 25) /**< I2S1 source is AF Input. */ +#define STM32_I2S1SEL_MCO1 (2 << 25) /**< I2S1 source is MCO1. */ +#define STM32_I2S1SEL_OFF 0xFFFFFFFFU /**< I2S1 clock is not required.*/ + +#define STM32_I2S2SEL_MASK (3 << 27) /**< I2S2SEL mask. */ +#define STM32_I2S2SEL_PLLR (0 << 27) /**< I2S2 source is PLLR. */ +#define STM32_I2S2SEL_AFIN (1 << 27) /**< I2S2 source is AF Input. */ +#define STM32_I2S2SEL_MCO1 (2 << 27) /**< I2S2 source is MCO1. */ +#define STM32_I2S2SEL_OFF 0xFFFFFFFFU /**< I2S2 clock is not required.*/ +/** @} */ + +/** + * @name RCC_DCKCFGR2 register bits definitions + * @{ + */ +#define STM32_I2CFMP1SEL_MASK (3 << 22) /**< I2CFMP1SEL mask. */ +#define STM32_I2CFMP1SEL_PCLK1 (0 << 22) /**< I2C1 source is APB/PCLK1. */ +#define STM32_I2CFMP1SEL_SYSCLK (1 << 22) /**< I2C1 source is SYSCLK. */ +#define STM32_I2CFMP1SEL_HSI (2 << 22) /**< I2C1 source is HSI. */ + +#define STM32_CK48MSEL_MASK (1 << 27) /**< CK48MSEL mask. */ +#define STM32_CK48MSEL_PLL (0 << 27) /**< PLL48CLK source is PLL. */ +#define STM32_CK48MSEL_PLLI2S (1 << 27) /**< PLL48CLK source is PLLI2S. */ +#define STM32_CK48MSEL_PLLALT (1 << 27) /**< Alias. */ + +#define STM32_SDIOSEL_MASK (1 << 28) /**< SDIOSEL mask. */ +#define STM32_SDIOSEL_PLL48CLK (0 << 28) /**< SDIO source is PLL48CLK. */ +#define STM32_SDIOSEL_SYSCLK (1 << 28) /**< SDIO source is SYSCLK. */ + +#define STM32_LPTIM1SEL_MASK (3 << 30) /**< LPTIM1 mask. */ +#define STM32_LPTIM1SEL_APB (0 << 30) /**< LPTIM1 source is APB. */ +#define STM32_LPTIM1SEL_HSI (1 << 30) /**< LPTIM1 source is HSI. */ +#define STM32_LPTIM1SEL_LSI (2 << 30) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_LSE (3 << 30) /**< LPTIM1 source is LSE. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables the backup RAM regulator. + */ +#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__) +#define STM32_BKPRAM_ENABLE FALSE +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief USB/SDIO clock setting. + */ +#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) +#define STM32_CLOCK48_REQUIRED TRUE +#endif + +/** + * @brief Main clock source selection. + * @note If the selected clock source is not the PLL then the PLL is not + * initialized and started. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLLs. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 8 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 192..432. + * @note The default value is calculated for a 96MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 384 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 96MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 4 +#endif + +/** + * @brief PLLQ multiplier value. + * @note The allowed values are 2..15. + * @note The default value is calculated for a 96MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 8 +#endif + +/** + * @brief AHB prescaler value. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief I2S clock source (pre-PLL). + */ +#if !defined(STM32_PLLI2SSRC) || defined(__DOXYGEN__) +#define STM32_PLLI2SSRC STM32_PLLI2SSRC_PLLSRC +#endif + +/** + * @brief I2S external clock value, zero if not present. + */ +#if !defined(STM32_I2SCKIN_VALUE) || defined(__DOXYGEN__) +#define STM32_I2SCKIN_VALUE 0 +#endif + +/** + * @brief PLLI2SM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 96MHz I2S clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLI2SM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SM_VALUE 8 +#endif + +/** + * @brief PLLI2SN multiplier value. + * @note The allowed values are 192..432, except for + * STM32F446 where values are 50...432. + * @note The default value is calculated for a 96MHz I2S clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SN_VALUE 192 +#endif + +/** + * @brief PLLI2SR divider value. + * @note The allowed values are 2..7. + * @note The default value is calculated for a 96MHz I2S clock + * output from an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SR_VALUE 4 +#endif + +/** + * @brief PLLI2SQ divider value. + * @note The allowed values are 2..15. + */ +#if !defined(STM32_PLLI2SQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SQ_VALUE 4 +#endif + +/** + * @brief PLLI2SDIVR divider value (SAI clock divider). + * @note The allowed values are 1..32. + */ +#if !defined(STM32_PLLI2SDIVR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SDIVR_VALUE 1 +#endif + +/** + * @brief PLLDIVR divider value (SAI clock divider). + * @note The allowed values are 1..32. + */ +#if !defined(STM32_PLLDIVR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLDIVR_VALUE 1 +#endif + +/** + * @brief SAI1SEL value (SAI1 clock source). + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#endif + +/** + * @brief SAI2SEL value (SAI2 clock source). + */ +#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#endif + +/** + * @brief TIM prescaler clock source. + */ +#if !defined(STM32_TIMPRE) || defined(__DOXYGEN__) +#define STM32_TIMPRE STM32_TIMPRE_PCLK +#endif + +/** + * @brief PLL48CLK clock source. + */ +#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief RTC HSE prescaler value. + */ +#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) +#define STM32_RTCPRE_VALUE 8 +#endif + +/** + * @brief MCO1 clock source value. + * @note The default value outputs HSI clock on MCO1 pin. + */ +#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#endif + +/** + * @brief MCO1 prescaler value. + * @note The default value outputs HSI clock on MCO1 pin. + */ +#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#endif + +/** + * @brief MCO2 clock source value. + * @note The default value outputs SYSCLK / 5 on MCO2 pin. + */ +#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#endif + +/** + * @brief MCO2 prescaler value. + * @note The default value outputs SYSCLK / 5 on MCO2 pin. + */ +#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F4xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined" +#endif + +#if defined(STM32F413xx) && !defined(STM32F413_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F413_MCUCONF not defined" +#endif + +/** + * @name Maximum frequency thresholds, wait states and + * parallelism for flash access. + * @{ + */ +#if defined(STM32F413xx) +#if (STM32_VDD >= 270) && (STM32_VDD <= 360) +#define STM32_0WS_THRESHOLD 25000000 +#define STM32_1WS_THRESHOLD 50000000 +#define STM32_2WS_THRESHOLD 75000000 +#define STM32_3WS_THRESHOLD 100000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 2 +#elif (STM32_VDD >= 240) && (STM32_VDD < 270) +#define STM32_0WS_THRESHOLD 20000000 +#define STM32_1WS_THRESHOLD 40000000 +#define STM32_2WS_THRESHOLD 60000000 +#define STM32_3WS_THRESHOLD 80000000 +#define STM32_4WS_THRESHOLD 100000000 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#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 100000000 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 1 +#elif (STM32_VDD >= 170) && (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 100000000 +#define STM32_7WS_THRESHOLD 0 +#define STM32_8WS_THRESHOLD 0 +#define STM32_FLASH_PSIZE 0 +#else +#error "invalid VDD voltage specified" +#endif +#define FLASH_SR_OPERR FLASH_SR_SOP +#endif /* defined(STM32F413xx) */ +/** @} */ + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_I2SSRC" +#endif + +#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SAI1SEL" +#endif + +#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SAI2SEL" +#endif +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#else /* STM32_HSECLK != 0 */ +#if defined(STM32_HSE_BYPASS) +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_BYP_MAX)" +#endif +#else /* !defined(STM32_HSE_BYPASS) */ +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif +#endif /* !defined(STM32_HSE_BYPASS) */ +#endif /* STM32_HSECLK != 0 */ +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ + ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_PLLI2SSRC" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief Clock frequency feeding PLLs. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSRCCLK STM32_HSECLK +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLSRCCLK STM32_HSICLK +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/** + * @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 PLL input clock frequency. + */ +#define STM32_PLLCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) + +/* + * PLLs input frequency range check. + */ +#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_CLOCK48_REQUIRED && \ + STM32_HAS_RCC_CK48MSEL && \ + (STM32_CK48MSEL == STM32_CK48MSEL_PLL)) || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ + (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 6) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLP STM32_PLLP_DIV2 +#elif STM32_PLLP_VALUE == 4 +#define STM32_PLLP STM32_PLLP_DIV4 +#elif STM32_PLLP_VALUE == 6 +#define STM32_PLLP STM32_PLLP_DIV6 +#elif STM32_PLLP_VALUE == 8 +#define STM32_PLLP STM32_PLLP_DIV8 +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLDIVR_VALUE field. + */ +#if ((STM32_PLLDIVR_VALUE >= 1) && (STM32_PLLDIVR_VALUE <= 32)) || \ + defined(__DOXYGEN__) +#define STM32_PLLDIVR ((STM32_PLLDIVR_VALUE - 1) << 8) +#else +#error "invalid STM32_PLLDIVR_VALUE value specified" +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) + +/* + * PLL output frequency range check. + */ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/* Calculating VOS settings, it is different for each sub-platform.*/ +#if defined(STM32F413xx) +#if STM32_SYSCLK <= 64000000 +#define STM32_VOS STM32_VOS_SCALE3 +#elif STM32_SYSCLK <= 84000000 +#define STM32_VOS STM32_VOS_SCALE2 +#else +#define STM32_VOS STM32_VOS_SCALE1 +#endif +#define STM32_OVERDRIVE_REQUIRED FALSE +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/* + * PLLI2S enable check. + */ +#if (STM32_HAS_RCC_PLLI2S && \ + (STM32_CLOCK48_REQUIRED && \ + (STM32_HAS_RCC_CK48MSEL && \ + STM32_RCC_CK48MSEL_USES_I2S && \ + (STM32_CK48MSEL == STM32_CK48MSEL_PLLI2S)) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S))) || \ + defined(__DOXYGEN__) + +/** + * @brief PLLI2S activation flag. + */ +#define STM32_ACTIVATE_PLLI2S TRUE +#else +#define STM32_ACTIVATE_PLLI2S FALSE +#endif + +/** + * @brief STM32_PLLI2SM field. + */ +#if ((STM32_PLLI2SM_VALUE >= 2) && (STM32_PLLI2SM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SM (STM32_PLLI2SM_VALUE << 0) +#else +#error "invalid STM32_PLLI2SM_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SN field. + */ +#if ((STM32_PLLI2SN_VALUE >= 50) && (STM32_PLLI2SN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) +#else +#error "invalid STM32_PLLI2SN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SQ field. + */ +#if ((STM32_PLLI2SQ_VALUE >= 2) && (STM32_PLLI2SQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SQ (STM32_PLLI2SQ_VALUE << 24) +#else +#error "invalid STM32_PLLI2SQ_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 STM32_PLLI2SDIVR field. + */ +#if ((STM32_PLLI2SDIVR_VALUE >= 1) && (STM32_PLLI2SDIVR_VALUE <= 32)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SDIVR ((STM32_PLLI2SR_VALUE - 1) << 0) +#else +#error "invalid STM32_PLLI2SDIVQ_VALUE value specified" +#endif + +/** + * @brief PLLI2S input clock frequency. + */ +#if STM32_HAS_RCC_I2SPLLSRC || defined(__DOXYGEN__) +#if (STM32_PLLI2SSRC == STM32_PLLI2SSRC_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLI2SM_VALUE) +#elif STM32_PLLI2SSRC == STM32_PLLI2SSRC_CKIN +#define STM32_PLLI2SCLKIN (STM32_I2SCKIN_VALUE / STM32_PLLI2SM_VALUE) +#else +#error "invalid STM32_PLLI2SSRC value specified" +#endif +#else +#define STM32_PLLI2SCLKIN (STM32_PLLSRCCLK / STM32_PLLM_VALUE) +#endif + +/** + * @brief PLLI2S VCO frequency. + */ +#define STM32_PLLI2SVCO (STM32_PLLI2SCLKIN * 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 Q output clock frequency. + */ +#define STM32_PLLI2S_Q_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SQ_VALUE) + +/** + * @brief PLLI2S R output clock frequency. + */ +#define STM32_PLLI2S_R_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) + +/** + * @brief PLLI2SP enable bit. + * @note Always 0, there is no PLLI2SP. + */ +#define STM32_PLLI2SP 0 + +/** + * @brief PLLSAI activation flag. + * @note Always FALSE, there is no PLLSAI. + */ +#define STM32_ACTIVATE_PLLSAI FALSE + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_TYPE2_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/platform.mk b/os/hal/ports/STM32/STM32F4xx/platform.mk index fdff0bdb8a..65f6845b72 100644 --- a/os/hal/ports/STM32/STM32F4xx/platform.mk +++ b/os/hal/ports/STM32/STM32F4xx/platform.mk @@ -1,49 +1,49 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/hal_lld.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/hal_efl_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/hal_lld.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/hal_efl_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_isr.c b/os/hal/ports/STM32/STM32F4xx/stm32_isr.c index 08237e1c33..f39c6f7b27 100644 --- a/os/hal/ports/STM32/STM32F4xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32F4xx/stm32_isr.c @@ -1,255 +1,255 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_isr.c - * @brief STM32F4xx ISR handler code. - * - * @addtogroup STM32F4xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_EXTI0_HANDLER) -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 0); - EXTI->PR = pr; - - exti_serve_irq(pr, 0); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI1_HANDLER) -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 1); - EXTI->PR = pr; - - exti_serve_irq(pr, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_HANDLER) -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 2); - EXTI->PR = pr; - - exti_serve_irq(pr, 2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI3_HANDLER) -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 3); - EXTI->PR = pr; - - exti_serve_irq(pr, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_HANDLER) -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 4); - EXTI->PR = pr; - - exti_serve_irq(pr, 4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | - (1U << 9)); - EXTI->PR = pr; - - exti_serve_irq(pr, 5); - exti_serve_irq(pr, 6); - exti_serve_irq(pr, 7); - exti_serve_irq(pr, 8); - exti_serve_irq(pr, 9); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | - (1U << 14) | (1U << 15)); - EXTI->PR = pr; - - exti_serve_irq(pr, 10); - exti_serve_irq(pr, 11); - exti_serve_irq(pr, 12); - exti_serve_irq(pr, 13); - exti_serve_irq(pr, 14); - exti_serve_irq(pr, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - -#if HAL_USE_PAL - nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); - nvicEnableVector(EXTI2_IRQn, STM32_IRQ_EXTI2_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); -#endif -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - -#if HAL_USE_PAL - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); -#endif -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_isr.c + * @brief STM32F4xx ISR handler code. + * + * @addtogroup STM32F4xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_EXTI0_HANDLER) +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 0); + EXTI->PR = pr; + + exti_serve_irq(pr, 0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI1_HANDLER) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 1); + EXTI->PR = pr; + + exti_serve_irq(pr, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_HANDLER) +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 2); + EXTI->PR = pr; + + exti_serve_irq(pr, 2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI3_HANDLER) +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 3); + EXTI->PR = pr; + + exti_serve_irq(pr, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_HANDLER) +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 4); + EXTI->PR = pr; + + exti_serve_irq(pr, 4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | + (1U << 9)); + EXTI->PR = pr; + + exti_serve_irq(pr, 5); + exti_serve_irq(pr, 6); + exti_serve_irq(pr, 7); + exti_serve_irq(pr, 8); + exti_serve_irq(pr, 9); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | + (1U << 14) | (1U << 15)); + EXTI->PR = pr; + + exti_serve_irq(pr, 10); + exti_serve_irq(pr, 11); + exti_serve_irq(pr, 12); + exti_serve_irq(pr, 13); + exti_serve_irq(pr, 14); + exti_serve_irq(pr, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + +#if HAL_USE_PAL + nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); + nvicEnableVector(EXTI2_IRQn, STM32_IRQ_EXTI2_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); +#endif +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +#if HAL_USE_PAL + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); +#endif +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_isr.h b/os/hal/ports/STM32/STM32F4xx/stm32_isr.h index 6a826f6a37..56b86a12c4 100644 --- a/os/hal/ports/STM32/STM32F4xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F4xx/stm32_isr.h @@ -1,275 +1,275 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_isr.h - * @brief STM32F4xx ISR handler header. - * - * @addtogroup STM32F4xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 -#define STM32_CAN2_TX_HANDLER Vector13C -#define STM32_CAN2_RX0_HANDLER Vector140 -#define STM32_CAN2_RX1_HANDLER Vector144 -#define STM32_CAN2_SCE_HANDLER Vector148 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 -#define STM32_CAN2_TX_NUMBER 63 -#define STM32_CAN2_RX0_NUMBER 64 -#define STM32_CAN2_RX1_NUMBER 65 -#define STM32_CAN2_SCE_NUMBER 66 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 - -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 - -#define STM32_I2C3_EVENT_HANDLER Vector160 -#define STM32_I2C3_ERROR_HANDLER Vector164 -#define STM32_I2C3_EVENT_NUMBER 72 -#define STM32_I2C3_ERROR_NUMBER 73 - -/* - * OTG units. - */ -#define STM32_OTG1_HANDLER Vector14C -#define STM32_OTG2_HANDLER Vector174 -#define STM32_OTG2_EP1OUT_HANDLER Vector168 -#define STM32_OTG2_EP1IN_HANDLER Vector16C - -#define STM32_OTG1_NUMBER 67 -#define STM32_OTG2_NUMBER 77 -#define STM32_OTG2_EP1OUT_NUMBER 74 -#define STM32_OTG2_EP1IN_NUMBER 75 - -/* - * SDIO unit. - */ -#define STM32_SDIO_HANDLER Vector104 - -#define STM32_SDIO_NUMBER 49 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER VectorA4 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_CC_HANDLER VectorF8 -#define STM32_TIM9_HANDLER VectorA0 -#define STM32_TIM10_HANDLER VectorA4 /* Note: same as STM32_TIM1_UP */ -#define STM32_TIM11_HANDLER VectorA8 -#define STM32_TIM12_HANDLER VectorEC -#define STM32_TIM13_HANDLER VectorF0 /* Note: same as STM32_TIM8_UP */ -#define STM32_TIM14_HANDLER VectorF4 - -#define STM32_TIM1_UP_NUMBER 25 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_CC_NUMBER 46 -#define STM32_TIM9_NUMBER 24 -#define STM32_TIM10_NUMBER 25 /* Note: same as STM32_TIM1_UP */ -#define STM32_TIM11_NUMBER 26 -#define STM32_TIM12_NUMBER 43 -#define STM32_TIM13_NUMBER 44 /* Note: same as STM32_TIM8_UP */ -#define STM32_TIM14_NUMBER 45 - -/* - * LPTIM units. - */ -#define STM32_LPTIM1_HANDLER Vector1C4 - -#define STM32_LPTIM1_NUMBER 97 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_USART6_HANDLER Vector15C -#define STM32_UART7_HANDLER Vector188 -#define STM32_UART8_HANDLER Vector18C - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_USART6_NUMBER 71 -#define STM32_UART7_NUMBER 82 -#define STM32_UART8_NUMBER 83 - -/* - * Ethernet - */ -#define ETH_IRQHandler Vector134 - -/* - * FSMC - */ -#define STM32_FSMC_HANDLER Vector100 - -#define STM32_FSMC_NUMBER 48 - -/* - * LTDC - */ -#define STM32_LTDC_EV_HANDLER Vector1A0 -#define STM32_LTDC_ER_HANDLER Vector1A4 - -#define STM32_LTDC_EV_NUMBER 88 -#define STM32_LTDC_ER_NUMBER 89 - -/* - * DMA2D - */ -#define STM32_DMA2D_HANDLER Vector1A8 - -#define STM32_DMA2D_NUMBER 90 - -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI0_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI1_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI2_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI3_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI4_PRIORITY 6 -#endif - -/** - * @brief EXTI5..9 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#endif - -/** - * @brief EXTI10..15 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_isr.h + * @brief STM32F4xx ISR handler header. + * + * @addtogroup STM32F4xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 +#define STM32_CAN2_TX_HANDLER Vector13C +#define STM32_CAN2_RX0_HANDLER Vector140 +#define STM32_CAN2_RX1_HANDLER Vector144 +#define STM32_CAN2_SCE_HANDLER Vector148 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 +#define STM32_CAN2_TX_NUMBER 63 +#define STM32_CAN2_RX0_NUMBER 64 +#define STM32_CAN2_RX1_NUMBER 65 +#define STM32_CAN2_SCE_NUMBER 66 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 + +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 + +#define STM32_I2C3_EVENT_HANDLER Vector160 +#define STM32_I2C3_ERROR_HANDLER Vector164 +#define STM32_I2C3_EVENT_NUMBER 72 +#define STM32_I2C3_ERROR_NUMBER 73 + +/* + * OTG units. + */ +#define STM32_OTG1_HANDLER Vector14C +#define STM32_OTG2_HANDLER Vector174 +#define STM32_OTG2_EP1OUT_HANDLER Vector168 +#define STM32_OTG2_EP1IN_HANDLER Vector16C + +#define STM32_OTG1_NUMBER 67 +#define STM32_OTG2_NUMBER 77 +#define STM32_OTG2_EP1OUT_NUMBER 74 +#define STM32_OTG2_EP1IN_NUMBER 75 + +/* + * SDIO unit. + */ +#define STM32_SDIO_HANDLER Vector104 + +#define STM32_SDIO_NUMBER 49 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER VectorA4 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_CC_HANDLER VectorF8 +#define STM32_TIM9_HANDLER VectorA0 +#define STM32_TIM10_HANDLER VectorA4 /* Note: same as STM32_TIM1_UP */ +#define STM32_TIM11_HANDLER VectorA8 +#define STM32_TIM12_HANDLER VectorEC +#define STM32_TIM13_HANDLER VectorF0 /* Note: same as STM32_TIM8_UP */ +#define STM32_TIM14_HANDLER VectorF4 + +#define STM32_TIM1_UP_NUMBER 25 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_CC_NUMBER 46 +#define STM32_TIM9_NUMBER 24 +#define STM32_TIM10_NUMBER 25 /* Note: same as STM32_TIM1_UP */ +#define STM32_TIM11_NUMBER 26 +#define STM32_TIM12_NUMBER 43 +#define STM32_TIM13_NUMBER 44 /* Note: same as STM32_TIM8_UP */ +#define STM32_TIM14_NUMBER 45 + +/* + * LPTIM units. + */ +#define STM32_LPTIM1_HANDLER Vector1C4 + +#define STM32_LPTIM1_NUMBER 97 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_USART6_HANDLER Vector15C +#define STM32_UART7_HANDLER Vector188 +#define STM32_UART8_HANDLER Vector18C + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_USART6_NUMBER 71 +#define STM32_UART7_NUMBER 82 +#define STM32_UART8_NUMBER 83 + +/* + * Ethernet + */ +#define ETH_IRQHandler Vector134 + +/* + * FSMC + */ +#define STM32_FSMC_HANDLER Vector100 + +#define STM32_FSMC_NUMBER 48 + +/* + * LTDC + */ +#define STM32_LTDC_EV_HANDLER Vector1A0 +#define STM32_LTDC_ER_HANDLER Vector1A4 + +#define STM32_LTDC_EV_NUMBER 88 +#define STM32_LTDC_ER_NUMBER 89 + +/* + * DMA2D + */ +#define STM32_DMA2D_HANDLER Vector1A8 + +#define STM32_DMA2D_NUMBER 90 + +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI0_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI1_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI2_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI3_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI4_PRIORITY 6 +#endif + +/** + * @brief EXTI5..9 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#endif + +/** + * @brief EXTI10..15 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h b/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h index cc401ce059..2734a14fdf 100644 --- a/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h @@ -1,1658 +1,1658 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f4xx.h. - * - * @addtogroup STM32F4xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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); \ - else \ - RCC->APB1LPENR &= ~(mask); \ - (void)RCC->APB1LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - RCC->APB1LPENR &= ~(mask); \ - (void)RCC->APB1LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccEnableAPB2(mask, lp) { \ - RCC->APB2ENR |= (mask); \ - if (lp) \ - RCC->APB2LPENR |= (mask); \ - else \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB1LPENR &= ~(mask); \ - (void)RCC->AHB1LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1LPENR &= ~(mask); \ - (void)RCC->AHB1LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB2LPENR &= ~(mask); \ - (void)RCC->AHB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2LPENR &= ~(mask); \ - (void)RCC->AHB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB3LPENR &= ~(mask); \ - (void)RCC->AHB3LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3LPENR &= ~(mask); \ - (void)RCC->AHB3LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableADC2() rccDisableAPB2(RCC_APB2ENR_ADC2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableADC3() rccDisableAPB2(RCC_APB2ENR_ADC3EN) - -/** - * @brief Resets the ADC3 peripheral. - * - * @api - */ -#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name BKPSRAM specific RCC operations - * @{ - */ -/** - * @brief Enables the BKPSRAM peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#ifdef RCC_AHB1ENR_BKPSRAMEN -#define rccEnableBKPSRAM(lp) rccEnableAHB1(RCC_AHB1ENR_BKPSRAMEN, lp) -#else -#define rccEnableBKPSRAM(lp) -#endif - -/** - * @brief Disables the BKPSRAM peripheral clock. - * - * @api - */ -#ifdef RCC_AHB1ENR_BKPSRAMEN -#define rccDisableBKPSRAM() rccDisableAHB1(RCC_AHB1ENR_BKPSRAMEN) -#else -#define rccDisableBKPSRAM() -#endif -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CAN1EN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) - -/** - * @brief Enables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) - -/** - * @brief Disables the CAN2 peripheral clock. - * - * @api - */ -#define rccDisableCAN2() rccDisableAPB1(RCC_APB1ENR_CAN2EN) - -/** - * @brief Resets the CAN2 peripheral. - * - * @api - */ -#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) -/** @} */ - -/** - * @name ETH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the ETH peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \ - RCC_AHB1ENR_ETHMACTXEN | \ - RCC_AHB1ENR_ETHMACRXEN, lp) - -/** - * @brief Disables the ETH peripheral clock. - * - * @api - */ -#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \ - RCC_AHB1ENR_ETHMACTXEN | \ - RCC_AHB1ENR_ETHMACRXEN) - -/** - * @brief Resets the ETH peripheral. - * - * @api - */ -#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1(RCC_APB1ENR_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) -/** @} */ - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @api - */ -#define rccEnableI2C4() rccEnableAPB1(RCC_APB1ENR_FMPI2C1EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C4(lp) rccDisableAPB1(RCC_APB1ENR_FMPI2C1EN, lp) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB1(RCC_APB1RSTR_FMPI2C1RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) - -/** - * @brief Disables the OTG_FS peripheral clock. - * - * @api - */ -#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) - -/** - * @brief Resets the OTG_FS peripheral. - * - * @api - */ -#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) - -/** - * @brief Enables the OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp) - -/** - * @brief Disables the OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableOTG_HS() rccDisableAHB1(RCC_AHB1ENR_OTGHSEN) - -/** - * @brief Resets the OTG_HS peripheral. - * - * @api - */ -#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHRST) - -/** - * @brief Enables the OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSULPIEN, lp) - -/** - * @brief Disables the OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableOTG_HSULPI() rccDisableAHB1(RCC_AHB1ENR_OTGHSULPIEN) -/** @} */ - -/** - * @name QUADSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the QUADSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) - -/** - * @brief Disables the QUADSPI1 peripheral clock. - * - * @api - */ -#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) - -/** - * @brief Resets the QUADSPI1 peripheral. - * - * @api - */ -#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) -/** @} */ - -/** - * @name SDIO peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDIO peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDIO(lp) rccEnableAPB2(RCC_APB2ENR_SDIOEN, lp) - -/** - * @brief Disables the SDIO peripheral clock. - * - * @api - */ -#define rccDisableSDIO() rccDisableAPB2(RCC_APB2ENR_SDIOEN) - -/** - * @brief Resets the SDIO peripheral. - * - * @api - */ -#define rccResetSDIO() rccResetAPB2(RCC_APB2RSTR_SDIORST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) - -/** - * @brief Enables the SPI4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) - -/** - * @brief Disables the SPI4 peripheral clock. - * - * @api - */ -#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) - -/** - * @brief Resets the SPI4 peripheral. - * - * @api - */ -#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) - -/** - * @brief Enables the SPI5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp) - -/** - * @brief Disables the SPI5 peripheral clock. - * - * @api - */ -#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN) - -/** - * @brief Resets the SPI5 peripheral. - * - * @api - */ -#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST) - -/** - * @brief Enables the SPI6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI6(lp) rccEnableAPB2(RCC_APB2ENR_SPI6EN, lp) - -/** - * @brief Disables the SPI6 peripheral clock. - * - * @api - */ -#define rccDisableSPI6() rccDisableAPB2(RCC_APB2ENR_SPI6EN) - -/** - * @brief Resets the SPI6 peripheral. - * - * @api - */ -#define rccResetSPI6() rccResetAPB2(RCC_APB2RSTR_SPI6RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM9 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) - -/** - * @brief Disables the TIM9 peripheral clock. - * - * @api - */ -#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) - -/** - * @brief Resets the TIM9 peripheral. - * - * @api - */ -#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) - -/** - * @brief Enables the TIM10 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) - -/** - * @brief Disables the TIM10 peripheral clock. - * - * @api - */ -#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) - -/** - * @brief Resets the TIM10 peripheral. - * - * @api - */ -#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) - -/** - * @brief Enables the TIM11 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) - -/** - * @brief Disables the TIM11 peripheral clock. - * - * @api - */ -#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) - -/** - * @brief Resets the TIM11 peripheral. - * - * @api - */ -#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) - -/** - * @brief Enables the TIM12 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) - -/** - * @brief Disables the TIM12 peripheral clock. - * - * @api - */ -#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) - -/** - * @brief Resets the TIM12 peripheral. - * - * @api - */ -#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) - -/** - * @brief Enables the TIM13 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) - -/** - * @brief Disables the TIM13 peripheral clock. - * - * @api - */ -#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) - -/** - * @brief Resets the TIM13 peripheral. - * - * @api - */ -#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) -/** @} */ - -/** - * @brief Enables the LPTIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPTIM1(lp) rccEnableAPB1(RCC_APB1ENR_LPTIM1EN, lp) - -/** - * @brief Disables the LPTIM1 peripheral clock. - * - * @api - */ -#define rccDisableLPTIM1() rccDisableAPB1(RCC_APB1ENR_LPTIM1EN, lp) - -/** - * @brief Resets the LPTIM1 peripheral. - * - * @api - */ -#define rccResetLPTIM1() rccResetAPB1(RCC_APB1RSTR_LPTIM1RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) - -/** - * @brief Resets the USART6 peripheral. - * - * @api - */ -#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) - -/** - * @brief Enables the UART7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART7(lp) rccEnableAPB1(RCC_APB1ENR_UART7EN, lp) - -/** - * @brief Disables the UART7 peripheral clock. - * - * @api - */ -#define rccDisableUART7() rccDisableAPB1(RCC_APB1ENR_UART7EN) - -/** - * @brief Resets the UART7 peripheral. - * - * @api - */ -#define rccResetUART7() rccResetAPB1(RCC_APB1RSTR_UART7RST) - -/** - * @brief Enables the UART8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART8(lp) rccEnableAPB1(RCC_APB1ENR_UART8EN, lp) - -/** - * @brief Disables the UART8 peripheral clock. - * - * @api - */ -#define rccDisableUART8() rccDisableAPB1(RCC_APB1ENR_UART8EN) - -/** - * @brief Resets the UART8 peripheral. - * - * @api - */ -#define rccResetUART8() rccResetAPB1(RCC_APB1RSTR_UART8RST) -/** @} */ - -/** - * @brief Enables the UART9 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART9(lp) rccEnableAPB2(RCC_APB2ENR_UART9EN, lp) - -/** - * @brief Disables the UART9 peripheral clock. - * - * @api - */ -#define rccDisableUART9() rccDisableAPB2(RCC_APB2ENR_UART9EN, lp) - -/** - * @brief Resets the UART9 peripheral. - * - * @api - */ -#define rccResetUART9() rccResetAPB2(RCC_APB2RSTR_UART9RST) -/** @} */ - -/** - * @brief Enables the UART10 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART10(lp) rccEnableAPB2(RCC_APB2ENR_UART10EN, lp) - -/** - * @brief Disables the UART10 peripheral clock. - * - * @api - */ -#define rccDisableUART10(lp) rccDisableAPB2(RCC_APB2ENR_UART10EN, lp) - -/** - * @brief Resets the UART10 peripheral. - * - * @api - */ -#define rccResetUART10() rccResetAPB2(RCC_APB2RSTR_UART10RST) -/** @} */ - -/** - * @name LTDC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the LTDC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLTDC(lp) rccEnableAPB2(RCC_APB2ENR_LTDCEN, lp) - -/** - * @brief Disables the LTDC peripheral clock. - * - * @api - */ -#define rccDisableLTDC() rccDisableAPB2(RCC_APB2ENR_LTDCEN) - -/** - * @brief Resets the LTDC peripheral. - * - * @api - */ -#define rccResetLTDC() rccResetAPB2(RCC_APB2RSTR_LTDCRST) - -/** - * @name DMA2D peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA2D peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2D(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2DEN, lp) - -/** - * @brief Disables the DMA2D peripheral clock. - * - * @api - */ -#define rccDisableDMA2D() rccDisableAHB1(RCC_AHB1ENR_DMA2DEN) - -/** - * @brief Resets the DMA2D peripheral. - * - * @api - */ -#define rccResetDMA2D() rccResetAHB1(RCC_AHB1RSTR_DMA2DRST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#if STM32_HAS_FSMC || defined(__DOXYGEN__) -#if STM32_FSMC_IS_FMC || defined(__DOXYGEN__) - #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) -#else - #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp) -#endif -#endif - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#if STM32_HAS_FSMC || defined(__DOXYGEN__) -#if STM32_FSMC_IS_FMC || defined(__DOXYGEN__) - #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) -#else - #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN) -#endif -#endif - -/** - * @brief Resets the FSMC peripheral. - * - * @api - */ -#if STM32_HAS_FSMC || defined(__DOXYGEN__) -#if STM32_FSMC_IS_FMC || defined(__DOXYGEN__) - #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) -#else - #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST) -#endif -#endif -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f4xx.h. + * + * @addtogroup STM32F4xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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); \ + else \ + RCC->APB1LPENR &= ~(mask); \ + (void)RCC->APB1LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + RCC->APB1LPENR &= ~(mask); \ + (void)RCC->APB1LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccEnableAPB2(mask, lp) { \ + RCC->APB2ENR |= (mask); \ + if (lp) \ + RCC->APB2LPENR |= (mask); \ + else \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB1LPENR &= ~(mask); \ + (void)RCC->AHB1LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1LPENR &= ~(mask); \ + (void)RCC->AHB1LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB2LPENR &= ~(mask); \ + (void)RCC->AHB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2LPENR &= ~(mask); \ + (void)RCC->AHB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB3LPENR &= ~(mask); \ + (void)RCC->AHB3LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3LPENR &= ~(mask); \ + (void)RCC->AHB3LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableADC2() rccDisableAPB2(RCC_APB2ENR_ADC2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableADC3() rccDisableAPB2(RCC_APB2ENR_ADC3EN) + +/** + * @brief Resets the ADC3 peripheral. + * + * @api + */ +#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name BKPSRAM specific RCC operations + * @{ + */ +/** + * @brief Enables the BKPSRAM peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#ifdef RCC_AHB1ENR_BKPSRAMEN +#define rccEnableBKPSRAM(lp) rccEnableAHB1(RCC_AHB1ENR_BKPSRAMEN, lp) +#else +#define rccEnableBKPSRAM(lp) +#endif + +/** + * @brief Disables the BKPSRAM peripheral clock. + * + * @api + */ +#ifdef RCC_AHB1ENR_BKPSRAMEN +#define rccDisableBKPSRAM() rccDisableAHB1(RCC_AHB1ENR_BKPSRAMEN) +#else +#define rccDisableBKPSRAM() +#endif +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CAN1EN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) + +/** + * @brief Enables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) + +/** + * @brief Disables the CAN2 peripheral clock. + * + * @api + */ +#define rccDisableCAN2() rccDisableAPB1(RCC_APB1ENR_CAN2EN) + +/** + * @brief Resets the CAN2 peripheral. + * + * @api + */ +#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) +/** @} */ + +/** + * @name ETH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the ETH peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \ + RCC_AHB1ENR_ETHMACTXEN | \ + RCC_AHB1ENR_ETHMACRXEN, lp) + +/** + * @brief Disables the ETH peripheral clock. + * + * @api + */ +#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \ + RCC_AHB1ENR_ETHMACTXEN | \ + RCC_AHB1ENR_ETHMACRXEN) + +/** + * @brief Resets the ETH peripheral. + * + * @api + */ +#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1(RCC_APB1ENR_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) +/** @} */ + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @api + */ +#define rccEnableI2C4() rccEnableAPB1(RCC_APB1ENR_FMPI2C1EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C4(lp) rccDisableAPB1(RCC_APB1ENR_FMPI2C1EN, lp) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB1(RCC_APB1RSTR_FMPI2C1RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) + +/** + * @brief Disables the OTG_FS peripheral clock. + * + * @api + */ +#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) + +/** + * @brief Resets the OTG_FS peripheral. + * + * @api + */ +#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) + +/** + * @brief Enables the OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp) + +/** + * @brief Disables the OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableOTG_HS() rccDisableAHB1(RCC_AHB1ENR_OTGHSEN) + +/** + * @brief Resets the OTG_HS peripheral. + * + * @api + */ +#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHRST) + +/** + * @brief Enables the OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSULPIEN, lp) + +/** + * @brief Disables the OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableOTG_HSULPI() rccDisableAHB1(RCC_AHB1ENR_OTGHSULPIEN) +/** @} */ + +/** + * @name QUADSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the QUADSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) + +/** + * @brief Disables the QUADSPI1 peripheral clock. + * + * @api + */ +#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) + +/** + * @brief Resets the QUADSPI1 peripheral. + * + * @api + */ +#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) +/** @} */ + +/** + * @name SDIO peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDIO peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDIO(lp) rccEnableAPB2(RCC_APB2ENR_SDIOEN, lp) + +/** + * @brief Disables the SDIO peripheral clock. + * + * @api + */ +#define rccDisableSDIO() rccDisableAPB2(RCC_APB2ENR_SDIOEN) + +/** + * @brief Resets the SDIO peripheral. + * + * @api + */ +#define rccResetSDIO() rccResetAPB2(RCC_APB2RSTR_SDIORST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) + +/** + * @brief Enables the SPI4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) + +/** + * @brief Disables the SPI4 peripheral clock. + * + * @api + */ +#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) + +/** + * @brief Resets the SPI4 peripheral. + * + * @api + */ +#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) + +/** + * @brief Enables the SPI5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp) + +/** + * @brief Disables the SPI5 peripheral clock. + * + * @api + */ +#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN) + +/** + * @brief Resets the SPI5 peripheral. + * + * @api + */ +#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST) + +/** + * @brief Enables the SPI6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI6(lp) rccEnableAPB2(RCC_APB2ENR_SPI6EN, lp) + +/** + * @brief Disables the SPI6 peripheral clock. + * + * @api + */ +#define rccDisableSPI6() rccDisableAPB2(RCC_APB2ENR_SPI6EN) + +/** + * @brief Resets the SPI6 peripheral. + * + * @api + */ +#define rccResetSPI6() rccResetAPB2(RCC_APB2RSTR_SPI6RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM9 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) + +/** + * @brief Disables the TIM9 peripheral clock. + * + * @api + */ +#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) + +/** + * @brief Resets the TIM9 peripheral. + * + * @api + */ +#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) + +/** + * @brief Enables the TIM10 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) + +/** + * @brief Disables the TIM10 peripheral clock. + * + * @api + */ +#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) + +/** + * @brief Resets the TIM10 peripheral. + * + * @api + */ +#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) + +/** + * @brief Enables the TIM11 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) + +/** + * @brief Disables the TIM11 peripheral clock. + * + * @api + */ +#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) + +/** + * @brief Resets the TIM11 peripheral. + * + * @api + */ +#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) + +/** + * @brief Enables the TIM12 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) + +/** + * @brief Disables the TIM12 peripheral clock. + * + * @api + */ +#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) + +/** + * @brief Resets the TIM12 peripheral. + * + * @api + */ +#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) + +/** + * @brief Enables the TIM13 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) + +/** + * @brief Disables the TIM13 peripheral clock. + * + * @api + */ +#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) + +/** + * @brief Resets the TIM13 peripheral. + * + * @api + */ +#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) +/** @} */ + +/** + * @brief Enables the LPTIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPTIM1(lp) rccEnableAPB1(RCC_APB1ENR_LPTIM1EN, lp) + +/** + * @brief Disables the LPTIM1 peripheral clock. + * + * @api + */ +#define rccDisableLPTIM1() rccDisableAPB1(RCC_APB1ENR_LPTIM1EN, lp) + +/** + * @brief Resets the LPTIM1 peripheral. + * + * @api + */ +#define rccResetLPTIM1() rccResetAPB1(RCC_APB1RSTR_LPTIM1RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) + +/** + * @brief Resets the USART6 peripheral. + * + * @api + */ +#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) + +/** + * @brief Enables the UART7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART7(lp) rccEnableAPB1(RCC_APB1ENR_UART7EN, lp) + +/** + * @brief Disables the UART7 peripheral clock. + * + * @api + */ +#define rccDisableUART7() rccDisableAPB1(RCC_APB1ENR_UART7EN) + +/** + * @brief Resets the UART7 peripheral. + * + * @api + */ +#define rccResetUART7() rccResetAPB1(RCC_APB1RSTR_UART7RST) + +/** + * @brief Enables the UART8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART8(lp) rccEnableAPB1(RCC_APB1ENR_UART8EN, lp) + +/** + * @brief Disables the UART8 peripheral clock. + * + * @api + */ +#define rccDisableUART8() rccDisableAPB1(RCC_APB1ENR_UART8EN) + +/** + * @brief Resets the UART8 peripheral. + * + * @api + */ +#define rccResetUART8() rccResetAPB1(RCC_APB1RSTR_UART8RST) +/** @} */ + +/** + * @brief Enables the UART9 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART9(lp) rccEnableAPB2(RCC_APB2ENR_UART9EN, lp) + +/** + * @brief Disables the UART9 peripheral clock. + * + * @api + */ +#define rccDisableUART9() rccDisableAPB2(RCC_APB2ENR_UART9EN, lp) + +/** + * @brief Resets the UART9 peripheral. + * + * @api + */ +#define rccResetUART9() rccResetAPB2(RCC_APB2RSTR_UART9RST) +/** @} */ + +/** + * @brief Enables the UART10 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART10(lp) rccEnableAPB2(RCC_APB2ENR_UART10EN, lp) + +/** + * @brief Disables the UART10 peripheral clock. + * + * @api + */ +#define rccDisableUART10(lp) rccDisableAPB2(RCC_APB2ENR_UART10EN, lp) + +/** + * @brief Resets the UART10 peripheral. + * + * @api + */ +#define rccResetUART10() rccResetAPB2(RCC_APB2RSTR_UART10RST) +/** @} */ + +/** + * @name LTDC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the LTDC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLTDC(lp) rccEnableAPB2(RCC_APB2ENR_LTDCEN, lp) + +/** + * @brief Disables the LTDC peripheral clock. + * + * @api + */ +#define rccDisableLTDC() rccDisableAPB2(RCC_APB2ENR_LTDCEN) + +/** + * @brief Resets the LTDC peripheral. + * + * @api + */ +#define rccResetLTDC() rccResetAPB2(RCC_APB2RSTR_LTDCRST) + +/** + * @name DMA2D peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA2D peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2D(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2DEN, lp) + +/** + * @brief Disables the DMA2D peripheral clock. + * + * @api + */ +#define rccDisableDMA2D() rccDisableAHB1(RCC_AHB1ENR_DMA2DEN) + +/** + * @brief Resets the DMA2D peripheral. + * + * @api + */ +#define rccResetDMA2D() rccResetAHB1(RCC_AHB1RSTR_DMA2DRST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#if STM32_HAS_FSMC || defined(__DOXYGEN__) +#if STM32_FSMC_IS_FMC || defined(__DOXYGEN__) + #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) +#else + #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp) +#endif +#endif + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#if STM32_HAS_FSMC || defined(__DOXYGEN__) +#if STM32_FSMC_IS_FMC || defined(__DOXYGEN__) + #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) +#else + #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN) +#endif +#endif + +/** + * @brief Resets the FSMC peripheral. + * + * @api + */ +#if STM32_HAS_FSMC || defined(__DOXYGEN__) +#if STM32_FSMC_IS_FMC || defined(__DOXYGEN__) + #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) +#else + #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST) +#endif +#endif +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_registry.h b/os/hal/ports/STM32/STM32F4xx/stm32_registry.h index 5072ce7443..bb8a3fb625 100644 --- a/os/hal/ports/STM32/STM32F4xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32F4xx/stm32_registry.h @@ -1,3174 +1,3174 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_registry.h - * @brief STM32F4xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -#if defined(STM32F469xx) || defined(STM32F479xx) -#define STM32F469_479xx -#define STM32F4XX - -#elif defined(STM32F446xx) -#define STM32F4XX - -#elif defined(STM32F439xx) || defined(STM32F429xx) -#define STM32F429_439xx -#define STM32F4XX - -#elif defined(STM32F437xx) || defined(STM32F427xx) -#define STM32F427_437xx -#define STM32F4XX - -#elif defined(STM32F413xx) -#define STM32F413xx -#define STM32F4XX - -#elif defined(STM32F412Cx) || defined(STM32F412Rx) || \ - defined(STM32F412Vx) || defined(STM32F412Zx) -#define STM32F412xx -#define STM32F4XX - -#elif defined(STM32F411xE) -#define STM32F411xx -#define STM32F4XX - -#elif defined(STM32F410Cx) || defined(STM32F410Rx) || \ - defined(STM32F410Tx) -#define STM32F410xx -#define STM32F4XX - -#elif defined(STM32F405xx) || defined(STM32F415xx) || \ - defined(STM32F407xx) || defined(STM32F417xx) -#define STM32F40_41xxx -#define STM32F4XX - -#elif defined(STM32F401xC) || defined(STM32F401xE) -#define STM32F401xx -#define STM32F4XX - -#elif defined(STM32F205xx) || defined(STM32F215xx) || \ - defined(STM32F207xx) || defined(STM32F217xx) -#define STM32F2XX - -#else -#error "STM32F2xx/F4xx device not specified" -#endif - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F4xx/STM32F2xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#if !defined(STM32F2XX) -#define STM32_RTC_HAS_SUBSECONDS TRUE -#else -#define STM32_RTC_HAS_SUBSECONDS FALSE -#endif -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 80 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 21 -#define STM32_RTC_WKUP_EXTI 22 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI21_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI22_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -/*===========================================================================*/ -/* STM32F469xx, STM32F479xx. */ -/*===========================================================================*/ - -#if defined(STM32F469_479xx) || defined(__DOXYGEN__) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI TRUE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 FALSE -#define STM32_HAS_RCC_I2SSRC TRUE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL TRUE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_Q_CLKOUT -#define STM32_TIMPRE_PRESCALE4 TRUE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE -#define STM32_ETH_HANDLER Vector134 -#define STM32_ETH_NUMBER 61 - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ TRUE -#define STM32_HAS_GPIOK TRUE - -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN | \ - RCC_AHB1ENR_GPIOJEN | \ - RCC_AHB1ENR_GPIOKEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_HANDLER Vector1AC -#define STM32_QUADSPI1_NUMBER 91 -#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_QUADSPI1_DMA_CHN 0x30000000 - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S FALSE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI6 TRUE -#define STM32_SPI6_SUPPORTS_I2S FALSE -#define STM32_SPI6_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 6) -#define STM32_SPI6_RX_DMA_CHN 0x01000000 -#define STM32_SPI6_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) -#define STM32_SPI6_TX_DMA_CHN 0x00100000 - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_UART7_RX_DMA_CHN 0x00005000 -#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_UART7_TX_DMA_CHN 0x00000050 - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART8_RX_DMA_CHN 0x05000000 -#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART8_TX_DMA_CHN 0x00000005 -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 7 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE -#define STM32_FSMC_HANDLER Vector100 -#define STM32_FSMC_NUMBER 48 - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F469_479xx) */ - -/*===========================================================================*/ -/* STM32F446xx. */ -/*===========================================================================*/ - -#if defined(STM32F446xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI TRUE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 TRUE -#define STM32_HAS_RCC_I2SSRC FALSE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL TRUE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_P_CLKOUT -#define STM32_TIMPRE_PRESCALE4 TRUE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE - -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_HANDLER Vector1B0 -#define STM32_QUADSPI1_NUMBER 92 -#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_QUADSPI1_DMA_CHN 0x30000000 - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 7 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE -#define STM32_FSMC_HANDLER Vector100 -#define STM32_FSMC_NUMBER 48 - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F446xx) */ - -/*===========================================================================*/ -/* STM32F439xx, STM32F429xx, STM32F437xx, STM32F427xx. */ -/*===========================================================================*/ - -#if defined(STM32F429_439xx) || defined(STM32F427_437xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI TRUE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 FALSE -#define STM32_HAS_RCC_I2SSRC TRUE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL FALSE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_TIMPRE_PRESCALE4 TRUE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE -#define STM32_ETH_HANDLER Vector134 -#define STM32_ETH_NUMBER 61 - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S FALSE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI6 TRUE -#define STM32_SPI6_SUPPORTS_I2S FALSE -#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI6_RX_DMA_CHN 0x01000000 -#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI6_TX_DMA_CHN 0x00100000 - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_UART7_RX_DMA_CHN 0x00005000 -#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_UART7_TX_DMA_CHN 0x00000050 - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART8_RX_DMA_CHN 0x05000000 -#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART8_TX_DMA_CHN 0x00000005 - -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 1 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 3 -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 5 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE -#define STM32_FSMC_HANDLER Vector100 -#define STM32_FSMC_NUMBER 48 - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F429_439xx) || defined(STM32F427_437xx) */ - -/*===========================================================================*/ -/* STM32F413xx. */ -/*===========================================================================*/ - -#if defined(STM32F413xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI FALSE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 TRUE -#define STM32_HAS_RCC_I2SSRC FALSE -#define STM32_HAS_RCC_I2SPLLSRC TRUE -#define STM32_HAS_RCC_CK48MSEL TRUE -#define STM32_RCC_CK48MSEL_USES_I2S TRUE -#define STM32_PLL48CLK_ALTSRC STM32_PLLI2S_Q_CLKOUT -#define STM32_TIMPRE_PRESCALE4 FALSE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#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 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 TRUE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_RX_DMA_CHN 0x00000310 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C3_TX_DMA_CHN 0x00630000 - -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_SUPPORTS_FMP TRUE -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_I2C4_RX_DMA_CHN 0x00001000 -#define STM32_I2C4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_I2C4_TX_DMA_CHN 0x00000020 - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_HANDLER Vector1B0 -#define STM32_QUADSPI1_NUMBER 92 -#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_QUADSPI1_DMA_CHN 0x30000000 - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX 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, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303200 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S TRUE -#define STM32_SPI4_I2S_FULLDUPLEX TRUE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_RX_DMA_CHN 0x00045004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S TRUE -#define STM32_SPI5_I2S_FULLDUPLEX TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07520000 - -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -#define STM32_HAS_LPTIM1 TRUE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x80000000 - -#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 - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_UART7_RX_DMA_CHN 0x00005000 -#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_UART7_TX_DMA_CHN 0x00000050 - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART8_RX_DMA_CHN 0x05000000 -#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART8_TX_DMA_CHN 0x00000005 - -#define STM32_HAS_UART9 TRUE -#define STM32_UART9_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_UART9_RX_DMA_CHN 0x00000000 -#define STM32_UART9_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 0) -#define STM32_UART9_TX_DMA_CHN 0x00000001 - -#define STM32_HAS_UART10 TRUE -#define STM32_UART10_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 0) -#define STM32_UART10_RX_DMA_CHN 0x00000005 -#define STM32_UART10_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_UART10_TX_DMA_CHN 0x60000000 - -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F413xx) */ - -/*===========================================================================*/ -/* STM32F412xx. */ -/*===========================================================================*/ - -#if defined(STM32F412xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI FALSE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 TRUE -#define STM32_HAS_RCC_I2SSRC FALSE -#define STM32_HAS_RCC_I2SPLLSRC TRUE -#define STM32_HAS_RCC_CK48MSEL TRUE -#define STM32_RCC_CK48MSEL_USES_I2S TRUE -#define STM32_PLL48CLK_ALTSRC STM32_PLLI2S_Q_CLKOUT -#define STM32_TIMPRE_PRESCALE4 FALSE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#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 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_RX_DMA_CHN 0x00000310 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C3_TX_DMA_CHN 0x00630000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_HANDLER Vector1B0 -#define STM32_QUADSPI1_NUMBER 92 -#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_QUADSPI1_DMA_CHN 0x30000000 - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S TRUE -#define STM32_SPI4_I2S_FULLDUPLEX TRUE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_RX_DMA_CHN 0x00045004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S TRUE -#define STM32_SPI5_I2S_FULLDUPLEX TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07520000 - -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_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 - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F412xx) */ - -/*===========================================================================*/ -/* STM32F411xx. */ -/*===========================================================================*/ - -#if defined(STM32F411xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI FALSE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 FALSE -#define STM32_HAS_RCC_I2SSRC TRUE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL FALSE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_Q_CLKOUT -#define STM32_TIMPRE_PRESCALE4 FALSE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#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 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOHEN) - -/* 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) |\ - STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ -+ STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_RX_DMA_CHN 0x00000310 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ -+ STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C3_TX_DMA_CHN 0x00630000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S TRUE -#define STM32_SPI4_I2S_FULLDUPLEX TRUE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S TRUE -#define STM32_SPI5_I2S_FULLDUPLEX TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 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 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE - -#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 - -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 1 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 3 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F411xx) */ - -/*===========================================================================*/ -/* STM32F410xx. */ -/*===========================================================================*/ - -#if defined(STM32F410xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI FALSE -#define STM32_HAS_RCC_PLLI2S FALSE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 TRUE -#define STM32_HAS_RCC_I2SSRC FALSE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL FALSE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_Q_CLKOUT -#define STM32_TIMPRE_PRESCALE4 FALSE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#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 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 FALSE - -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0)) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C4_RX_DMA_CHN 0x00002007 -#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) |\ - STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_I2C4_TX_DMA_CHN 0x00040020 - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX 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, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00003200 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S TRUE -#define STM32_SPI5_I2S_FULLDUPLEX TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM2 FALSE -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 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) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_RX_DMA_CHN 0x60400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE - -#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 - -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F410xx) */ - -/*===========================================================================*/ -/* STM32F405xx, STM32F415xx, STM32F407xx, STM32F417xx, STM32F205xx, */ -/* STM32F215xx, STM32F207xx, STM32F217xx. */ -/*===========================================================================*/ - -#if defined(STM32F40_41xxx) || defined(STM32F2XX) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI FALSE -#define STM32_HAS_RCC_PLLI2S TRUE -#define STM32_HAS_RCC_DCKCFGR FALSE -#define STM32_HAS_RCC_DCKCFGR2 FALSE -#define STM32_HAS_RCC_I2SSRC TRUE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL FALSE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_TIMPRE_PRESCALE4 TRUE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F205xx) || \ - defined(STM32F215xx) -#define STM32_HAS_ETH FALSE -#else -#define STM32_HAS_ETH TRUE -#define STM32_ETH_HANDLER Vector134 -#define STM32_ETH_NUMBER 61 -#endif - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 1 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 3 -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 5 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F40_41xxx) || defined(STM32F2XX) */ - -/*===========================================================================*/ -/* STM32F401xx. */ -/*===========================================================================*/ - -#if defined(STM32F401xx) - -/* Clock tree attributes.*/ -#define STM32_HAS_RCC_PLLSAI FALSE -#define STM32_HAS_RCC_PLLI2S FALSE -#define STM32_HAS_RCC_DCKCFGR TRUE -#define STM32_HAS_RCC_DCKCFGR2 FALSE -#define STM32_HAS_RCC_I2SSRC FALSE -#define STM32_HAS_RCC_I2SPLLSRC FALSE -#define STM32_HAS_RCC_CK48MSEL FALSE -#define STM32_RCC_CK48MSEL_USES_I2S FALSE -#define STM32_TIMPRE_PRESCALE4 FALSE - -/* ADC attributes.*/ -#define STM32_ADC_HANDLER Vector88 -#define STM32_ADC_NUMBER 18 - -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 - -#define STM32_HAS_DMA2 TRUE -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0x00000000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 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 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE - -#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 - -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 1 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 3 -#define STM32_HAS_OTG2 FALSE - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -#endif /* defined(STM32F401xx) */ -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_registry.h + * @brief STM32F4xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +#if defined(STM32F469xx) || defined(STM32F479xx) +#define STM32F469_479xx +#define STM32F4XX + +#elif defined(STM32F446xx) +#define STM32F4XX + +#elif defined(STM32F439xx) || defined(STM32F429xx) +#define STM32F429_439xx +#define STM32F4XX + +#elif defined(STM32F437xx) || defined(STM32F427xx) +#define STM32F427_437xx +#define STM32F4XX + +#elif defined(STM32F413xx) +#define STM32F413xx +#define STM32F4XX + +#elif defined(STM32F412Cx) || defined(STM32F412Rx) || \ + defined(STM32F412Vx) || defined(STM32F412Zx) +#define STM32F412xx +#define STM32F4XX + +#elif defined(STM32F411xE) +#define STM32F411xx +#define STM32F4XX + +#elif defined(STM32F410Cx) || defined(STM32F410Rx) || \ + defined(STM32F410Tx) +#define STM32F410xx +#define STM32F4XX + +#elif defined(STM32F405xx) || defined(STM32F415xx) || \ + defined(STM32F407xx) || defined(STM32F417xx) +#define STM32F40_41xxx +#define STM32F4XX + +#elif defined(STM32F401xC) || defined(STM32F401xE) +#define STM32F401xx +#define STM32F4XX + +#elif defined(STM32F205xx) || defined(STM32F215xx) || \ + defined(STM32F207xx) || defined(STM32F217xx) +#define STM32F2XX + +#else +#error "STM32F2xx/F4xx device not specified" +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F4xx/STM32F2xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#if !defined(STM32F2XX) +#define STM32_RTC_HAS_SUBSECONDS TRUE +#else +#define STM32_RTC_HAS_SUBSECONDS FALSE +#endif +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 80 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 21 +#define STM32_RTC_WKUP_EXTI 22 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI21_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI22_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +/*===========================================================================*/ +/* STM32F469xx, STM32F479xx. */ +/*===========================================================================*/ + +#if defined(STM32F469_479xx) || defined(__DOXYGEN__) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI TRUE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 FALSE +#define STM32_HAS_RCC_I2SSRC TRUE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL TRUE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_Q_CLKOUT +#define STM32_TIMPRE_PRESCALE4 TRUE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE +#define STM32_ETH_HANDLER Vector134 +#define STM32_ETH_NUMBER 61 + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ TRUE +#define STM32_HAS_GPIOK TRUE + +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN | \ + RCC_AHB1ENR_GPIOJEN | \ + RCC_AHB1ENR_GPIOKEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_HANDLER Vector1AC +#define STM32_QUADSPI1_NUMBER 91 +#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_QUADSPI1_DMA_CHN 0x30000000 + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S FALSE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI6 TRUE +#define STM32_SPI6_SUPPORTS_I2S FALSE +#define STM32_SPI6_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 6) +#define STM32_SPI6_RX_DMA_CHN 0x01000000 +#define STM32_SPI6_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) +#define STM32_SPI6_TX_DMA_CHN 0x00100000 + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_UART7_RX_DMA_CHN 0x00005000 +#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_UART7_TX_DMA_CHN 0x00000050 + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART8_RX_DMA_CHN 0x05000000 +#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART8_TX_DMA_CHN 0x00000005 +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 7 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE +#define STM32_FSMC_HANDLER Vector100 +#define STM32_FSMC_NUMBER 48 + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F469_479xx) */ + +/*===========================================================================*/ +/* STM32F446xx. */ +/*===========================================================================*/ + +#if defined(STM32F446xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI TRUE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 TRUE +#define STM32_HAS_RCC_I2SSRC FALSE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL TRUE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_P_CLKOUT +#define STM32_TIMPRE_PRESCALE4 TRUE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE + +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_HANDLER Vector1B0 +#define STM32_QUADSPI1_NUMBER 92 +#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_QUADSPI1_DMA_CHN 0x30000000 + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 7 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE +#define STM32_FSMC_HANDLER Vector100 +#define STM32_FSMC_NUMBER 48 + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F446xx) */ + +/*===========================================================================*/ +/* STM32F439xx, STM32F429xx, STM32F437xx, STM32F427xx. */ +/*===========================================================================*/ + +#if defined(STM32F429_439xx) || defined(STM32F427_437xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI TRUE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 FALSE +#define STM32_HAS_RCC_I2SSRC TRUE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL FALSE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_TIMPRE_PRESCALE4 TRUE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE +#define STM32_ETH_HANDLER Vector134 +#define STM32_ETH_NUMBER 61 + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S FALSE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI6 TRUE +#define STM32_SPI6_SUPPORTS_I2S FALSE +#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI6_RX_DMA_CHN 0x01000000 +#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI6_TX_DMA_CHN 0x00100000 + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_UART7_RX_DMA_CHN 0x00005000 +#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_UART7_TX_DMA_CHN 0x00000050 + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART8_RX_DMA_CHN 0x05000000 +#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART8_TX_DMA_CHN 0x00000005 + +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 1 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 3 +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 5 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE +#define STM32_FSMC_HANDLER Vector100 +#define STM32_FSMC_NUMBER 48 + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F429_439xx) || defined(STM32F427_437xx) */ + +/*===========================================================================*/ +/* STM32F413xx. */ +/*===========================================================================*/ + +#if defined(STM32F413xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI FALSE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 TRUE +#define STM32_HAS_RCC_I2SSRC FALSE +#define STM32_HAS_RCC_I2SPLLSRC TRUE +#define STM32_HAS_RCC_CK48MSEL TRUE +#define STM32_RCC_CK48MSEL_USES_I2S TRUE +#define STM32_PLL48CLK_ALTSRC STM32_PLLI2S_Q_CLKOUT +#define STM32_TIMPRE_PRESCALE4 FALSE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#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 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 TRUE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_RX_DMA_CHN 0x00000310 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C3_TX_DMA_CHN 0x00630000 + +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_SUPPORTS_FMP TRUE +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_I2C4_RX_DMA_CHN 0x00001000 +#define STM32_I2C4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_I2C4_TX_DMA_CHN 0x00000020 + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_HANDLER Vector1B0 +#define STM32_QUADSPI1_NUMBER 92 +#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_QUADSPI1_DMA_CHN 0x30000000 + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX 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, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303200 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S TRUE +#define STM32_SPI4_I2S_FULLDUPLEX TRUE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_RX_DMA_CHN 0x00045004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S TRUE +#define STM32_SPI5_I2S_FULLDUPLEX TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07520000 + +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +#define STM32_HAS_LPTIM1 TRUE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x80000000 + +#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 + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_UART7_RX_DMA_CHN 0x00005000 +#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_UART7_TX_DMA_CHN 0x00000050 + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART8_RX_DMA_CHN 0x05000000 +#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART8_TX_DMA_CHN 0x00000005 + +#define STM32_HAS_UART9 TRUE +#define STM32_UART9_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_UART9_RX_DMA_CHN 0x00000000 +#define STM32_UART9_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 0) +#define STM32_UART9_TX_DMA_CHN 0x00000001 + +#define STM32_HAS_UART10 TRUE +#define STM32_UART10_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 0) +#define STM32_UART10_RX_DMA_CHN 0x00000005 +#define STM32_UART10_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_UART10_TX_DMA_CHN 0x60000000 + +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F413xx) */ + +/*===========================================================================*/ +/* STM32F412xx. */ +/*===========================================================================*/ + +#if defined(STM32F412xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI FALSE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 TRUE +#define STM32_HAS_RCC_I2SSRC FALSE +#define STM32_HAS_RCC_I2SPLLSRC TRUE +#define STM32_HAS_RCC_CK48MSEL TRUE +#define STM32_RCC_CK48MSEL_USES_I2S TRUE +#define STM32_PLL48CLK_ALTSRC STM32_PLLI2S_Q_CLKOUT +#define STM32_TIMPRE_PRESCALE4 FALSE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#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 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_RX_DMA_CHN 0x00000310 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C3_TX_DMA_CHN 0x00630000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_HANDLER Vector1B0 +#define STM32_QUADSPI1_NUMBER 92 +#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_QUADSPI1_DMA_CHN 0x30000000 + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S TRUE +#define STM32_SPI4_I2S_FULLDUPLEX TRUE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_RX_DMA_CHN 0x00045004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S TRUE +#define STM32_SPI5_I2S_FULLDUPLEX TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07520000 + +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_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 + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F412xx) */ + +/*===========================================================================*/ +/* STM32F411xx. */ +/*===========================================================================*/ + +#if defined(STM32F411xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI FALSE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 FALSE +#define STM32_HAS_RCC_I2SSRC TRUE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL FALSE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_Q_CLKOUT +#define STM32_TIMPRE_PRESCALE4 FALSE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#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 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOHEN) + +/* 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) |\ + STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ ++ STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_RX_DMA_CHN 0x00000310 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ ++ STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C3_TX_DMA_CHN 0x00630000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S TRUE +#define STM32_SPI4_I2S_FULLDUPLEX TRUE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S TRUE +#define STM32_SPI5_I2S_FULLDUPLEX TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 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 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE + +#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 + +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 1 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 3 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F411xx) */ + +/*===========================================================================*/ +/* STM32F410xx. */ +/*===========================================================================*/ + +#if defined(STM32F410xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI FALSE +#define STM32_HAS_RCC_PLLI2S FALSE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 TRUE +#define STM32_HAS_RCC_I2SSRC FALSE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL FALSE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_PLL48CLK_ALTSRC STM32_PLLSAI_Q_CLKOUT +#define STM32_TIMPRE_PRESCALE4 FALSE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#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 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 FALSE + +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0)) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C4_RX_DMA_CHN 0x00002007 +#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) |\ + STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_I2C4_TX_DMA_CHN 0x00040020 + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX 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, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00003200 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S TRUE +#define STM32_SPI5_I2S_FULLDUPLEX TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM2 FALSE +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 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) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_RX_DMA_CHN 0x60400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE + +#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 + +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F410xx) */ + +/*===========================================================================*/ +/* STM32F405xx, STM32F415xx, STM32F407xx, STM32F417xx, STM32F205xx, */ +/* STM32F215xx, STM32F207xx, STM32F217xx. */ +/*===========================================================================*/ + +#if defined(STM32F40_41xxx) || defined(STM32F2XX) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI FALSE +#define STM32_HAS_RCC_PLLI2S TRUE +#define STM32_HAS_RCC_DCKCFGR FALSE +#define STM32_HAS_RCC_DCKCFGR2 FALSE +#define STM32_HAS_RCC_I2SSRC TRUE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL FALSE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_TIMPRE_PRESCALE4 TRUE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F205xx) || \ + defined(STM32F215xx) +#define STM32_HAS_ETH FALSE +#else +#define STM32_HAS_ETH TRUE +#define STM32_ETH_HANDLER Vector134 +#define STM32_ETH_NUMBER 61 +#endif + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 1 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 3 +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 5 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F40_41xxx) || defined(STM32F2XX) */ + +/*===========================================================================*/ +/* STM32F401xx. */ +/*===========================================================================*/ + +#if defined(STM32F401xx) + +/* Clock tree attributes.*/ +#define STM32_HAS_RCC_PLLSAI FALSE +#define STM32_HAS_RCC_PLLI2S FALSE +#define STM32_HAS_RCC_DCKCFGR TRUE +#define STM32_HAS_RCC_DCKCFGR2 FALSE +#define STM32_HAS_RCC_I2SSRC FALSE +#define STM32_HAS_RCC_I2SPLLSRC FALSE +#define STM32_HAS_RCC_CK48MSEL FALSE +#define STM32_RCC_CK48MSEL_USES_I2S FALSE +#define STM32_TIMPRE_PRESCALE4 FALSE + +/* ADC attributes.*/ +#define STM32_ADC_HANDLER Vector88 +#define STM32_ADC_NUMBER 18 + +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 + +#define STM32_HAS_DMA2 TRUE +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0x00000000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 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 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE + +#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 + +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 1 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 3 +#define STM32_HAS_OTG2 FALSE + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +#endif /* defined(STM32F401xx) */ +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F7xx/hal_lld.c b/os/hal/ports/STM32/STM32F7xx/hal_lld.c index f57e097bc5..52a35a16da 100644 --- a/os/hal/ports/STM32/STM32F7xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32F7xx/hal_lld.c @@ -1,318 +1,319 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/hal_lld.c - * @brief STM32F7xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f7xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR1 |= PWR_CR1_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - -#if STM32_BKPRAM_ENABLE - rccEnableBKPSRAM(true); - - PWR->CSR1 |= PWR_CSR1_BRE; - while ((PWR->CSR1 & PWR_CSR1_BRR) == 0) - ; /* Waits until the regulator is stable */ -#else - PWR->CSR1 &= ~PWR_CSR1_BRE; -#endif /* STM32_BKPRAM_ENABLE */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. AHB3 is not reseted because it could have - been initialized in the board initialization file (board.c). - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB1(~STM32_GPIO_EN_MASK); - rccResetAHB2(~0); - rccResetAPB1(~RCC_APB1RSTR_PWRRST); - rccResetAPB2(~0); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - -#if STM32_SRAM2_NOCACHE - /* The SRAM2 bank can optionally made a non cache-able area for use by - DMA engines.*/ - mpuConfigureRegion(MPU_REGION_7, - SRAM2_BASE, - MPU_RASR_ATTR_AP_RW_RW | - MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_16K | - MPU_RASR_ENABLE); - mpuEnable(MPU_CTRL_PRIVDEFENA); - - /* Invalidating data cache to make sure that the MPU settings are taken - immediately.*/ - SCB_CleanInvalidateDCache(); -#endif - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR1 |= PWR_CR1_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32F2xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enabled.*/ -#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR_RTCEN) - RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_RTCEN; -#else - RCC->APB1ENR = RCC_APB1ENR_PWREN; -#endif - - /* PWR initialization.*/ - PWR->CR1 = STM32_VOS; - - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. Clearing the register has to be postponed after HSI is the - new source.*/ - RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers finally cleared to reset values.*/ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN | - STM32_PLLM; - RCC->CR |= RCC_CR_PLLON; - - /* Synchronization with voltage regulator stabilization.*/ - while ((PWR->CSR1 & PWR_CSR1_VOSRDY) == 0) - ; /* Waits until power regulator is stable. */ - -#if STM32_OVERDRIVE_REQUIRED - /* Overdrive activation performed after activating the PLL in order to save - time as recommended in RM in "Entering Over-drive mode" paragraph.*/ - PWR->CR1 |= PWR_CR1_ODEN; - while (!(PWR->CSR1 & PWR_CSR1_ODRDY)) - ; - PWR->CR1 |= PWR_CR1_ODSWEN; - while (!(PWR->CSR1 & PWR_CSR1_ODSWRDY)) - ; -#endif /* STM32_OVERDRIVE_REQUIRED */ - - /* Waiting for PLL lock.*/ - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; -#endif /* STM32_OVERDRIVE_REQUIRED */ - -#if STM32_ACTIVATE_PLLI2S - /* PLLI2S activation.*/ - RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SQ | STM32_PLLI2SP | - STM32_PLLI2SN; - RCC->CR |= RCC_CR_PLLI2SON; - - /* Waiting for PLL lock.*/ - while (!(RCC->CR & RCC_CR_PLLI2SRDY)) - ; -#endif - -#if STM32_ACTIVATE_PLLSAI - /* PLLSAI activation.*/ - RCC->PLLSAICFGR = STM32_PLLSAIR | STM32_PLLSAIQ | STM32_PLLSAIP | - STM32_PLLSAIN; - RCC->CR |= RCC_CR_PLLSAION; - - /* Waiting for PLL lock.*/ - while (!(RCC->CR & RCC_CR_PLLSAIRDY)) - ; -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CFGR = STM32_MCO2SEL | STM32_MCO2PRE | STM32_MCO1PRE | STM32_I2SSRC | - STM32_MCO1SEL | STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | - STM32_HPRE; - - /* DCKCFGR1 register initialization, note, must take care of the _OFF - pseudo settings.*/ - { - uint32_t dckcfgr1 = STM32_PLLI2SDIVQ | STM32_PLLSAIDIVQ | STM32_PLLSAIDIVR; -#if STM32_SAI2SEL != STM32_SAI2SEL_OFF - dckcfgr1 |= STM32_SAI2SEL; -#endif -#if STM32_SAI1SEL != STM32_SAI1SEL_OFF - dckcfgr1 |= STM32_SAI1SEL; -#endif -#if STM32_TIMPRE_ENABLE == TRUE - dckcfgr1 |= RCC_DCKCFGR1_TIMPRE; -#endif - RCC->DCKCFGR1 = dckcfgr1; - } - - /* Peripheral clock sources.*/ - RCC->DCKCFGR2 = STM32_SDMMC2SEL | STM32_SDMMC1SEL | STM32_CK48MSEL | - STM32_CECSEL | STM32_LPTIM1SEL | STM32_I2C4SEL | - STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | - STM32_UART8SEL | STM32_UART7SEL | STM32_USART6SEL | - STM32_UART5SEL | STM32_UART4SEL | STM32_USART3SEL | - STM32_USART2SEL | STM32_USART1SEL; - - /* Flash setup.*/ - FLASH->ACR = FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif -#endif /* STM32_NO_INIT */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/hal_lld.c + * @brief STM32F7xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f7xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR1 |= PWR_CR1_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + +#if STM32_BKPRAM_ENABLE + rccEnableBKPSRAM(true); + + PWR->CSR1 |= PWR_CSR1_BRE; + while ((PWR->CSR1 & PWR_CSR1_BRR) == 0) + ; /* Waits until the regulator is stable */ +#else + PWR->CSR1 &= ~PWR_CSR1_BRE; +#endif /* STM32_BKPRAM_ENABLE */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. AHB3 is not reseted because it could have + been initialized in the board initialization file (board.c). + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~STM32_GPIO_EN_MASK); + rccResetAHB2(~0); + rccResetAPB1(~RCC_APB1RSTR_PWRRST); + rccResetAPB2(~0); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + +#if STM32_SRAM2_NOCACHE + /* The SRAM2 bank can optionally made a non cache-able area for use by + DMA engines.*/ + mpuConfigureRegion(MPU_REGION_7, + SRAM2_BASE, + MPU_RASR_ATTR_AP_RW_RW | + MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_16K | + MPU_RASR_ENABLE); + mpuEnable(MPU_CTRL_PRIVDEFENA); + + /* Invalidating data cache to make sure that the MPU settings are taken + immediately.*/ + SCB_CleanInvalidateDCache(); +#endif + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR1 |= PWR_CR1_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32F2xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enabled.*/ +#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR_RTCEN) + RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_RTCEN; +#else + RCC->APB1ENR = RCC_APB1ENR_PWREN; +#endif + + /* PWR initialization.*/ + PWR->CR1 = STM32_VOS; + + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. Clearing the register has to be postponed after HSI is the + new source.*/ + RCC->CFGR &= ~RCC_CFGR_SW; /* Reset SW, selecting HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers finally cleared to reset values.*/ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN | + STM32_PLLM; + RCC->CR |= RCC_CR_PLLON; + + /* Synchronization with voltage regulator stabilization.*/ + while ((PWR->CSR1 & PWR_CSR1_VOSRDY) == 0) + ; /* Waits until power regulator is stable. */ + +#if STM32_OVERDRIVE_REQUIRED + /* Overdrive activation performed after activating the PLL in order to save + time as recommended in RM in "Entering Over-drive mode" paragraph.*/ + PWR->CR1 |= PWR_CR1_ODEN; + while (!(PWR->CSR1 & PWR_CSR1_ODRDY)) + ; + PWR->CR1 |= PWR_CR1_ODSWEN; + while (!(PWR->CSR1 & PWR_CSR1_ODSWRDY)) + ; +#endif /* STM32_OVERDRIVE_REQUIRED */ + + /* Waiting for PLL lock.*/ + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; +#endif /* STM32_OVERDRIVE_REQUIRED */ + +#if STM32_ACTIVATE_PLLI2S + /* PLLI2S activation.*/ + RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SQ | STM32_PLLI2SP | + STM32_PLLI2SN; + RCC->CR |= RCC_CR_PLLI2SON; + + /* Waiting for PLL lock.*/ + while (!(RCC->CR & RCC_CR_PLLI2SRDY)) + ; +#endif + +#if STM32_ACTIVATE_PLLSAI + /* PLLSAI activation.*/ + RCC->PLLSAICFGR = STM32_PLLSAIR | STM32_PLLSAIQ | STM32_PLLSAIP | + STM32_PLLSAIN; + RCC->CR |= RCC_CR_PLLSAION; + + /* Waiting for PLL lock.*/ + while (!(RCC->CR & RCC_CR_PLLSAIRDY)) + ; +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CFGR = STM32_MCO2SEL | STM32_MCO2PRE | STM32_MCO1PRE | STM32_I2SSRC | + STM32_MCO1SEL | STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE; + + /* DCKCFGR1 register initialization, note, must take care of the _OFF + pseudo settings.*/ + { + uint32_t dckcfgr1 = STM32_PLLI2SDIVQ | STM32_PLLSAIDIVQ | STM32_PLLSAIDIVR; +#if STM32_SAI2SEL != STM32_SAI2SEL_OFF + dckcfgr1 |= STM32_SAI2SEL; +#endif +#if STM32_SAI1SEL != STM32_SAI1SEL_OFF + dckcfgr1 |= STM32_SAI1SEL; +#endif +#if STM32_TIMPRE_ENABLE == TRUE + dckcfgr1 |= RCC_DCKCFGR1_TIMPRE; +#endif + RCC->DCKCFGR1 = dckcfgr1; + } + + /* Peripheral clock sources.*/ + RCC->DCKCFGR2 = STM32_SDMMC2SEL | STM32_SDMMC1SEL | STM32_CK48MSEL | + STM32_CECSEL | STM32_LPTIM1SEL | STM32_I2C4SEL | + STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | + STM32_UART8SEL | STM32_UART7SEL | STM32_USART6SEL | + STM32_UART5SEL | STM32_UART4SEL | STM32_USART3SEL | + STM32_USART2SEL | STM32_USART1SEL; + + /* Flash setup.*/ + FLASH->ACR = FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F7xx/hal_lld.h b/os/hal/ports/STM32/STM32F7xx/hal_lld.h index e0848775f0..3a9245af91 100644 --- a/os/hal/ports/STM32/STM32F7xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32F7xx/hal_lld.h @@ -1,2200 +1,2208 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/hal_lld.h - * @brief STM32F7xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * - STM32_VDD (as hundredths of Volt). - * . - * One of the following macros must also be defined: - * - STM32F722xx, STM32F723xx very high-performance MCUs. - * - STM32F732xx, STM32F733xx very high-performance MCUs. - * - STM32F745xx, STM32F746xx, STM32F756xx very high-performance MCUs. - * - STM32F765xx, STM32F767xx, STM32F769xx very high-performance MCUs. - * - STM32F777xx, STM32F779xx very high-performance MCUs. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Defines the support for realtime counters in the HAL. - */ -#define HAL_IMPLEMENTS_COUNTERS TRUE - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32F722xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" - -#elif defined(STM32F723xx) -#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" - -#elif defined(STM32F732xx) -#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" - -#elif defined(STM32F733xx) -#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" - -#elif defined(STM32F745xx) -#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" - -#elif defined(STM32F746xx) -#define PLATFORM_NAME "STM32F746 Very High Performance with DSP and FPU" - -#elif defined(STM32F756xx) -#define PLATFORM_NAME "STM32F756 Very High Performance with DSP and FPU" - -#elif defined(STM32F765xx) -#define PLATFORM_NAME "STM32F767 Very High Performance with DSP and DP FPU" - -#elif defined(STM32F767xx) -#define PLATFORM_NAME "STM32F767 Very High Performance with DSP and DP FPU" - -#elif defined(STM32F769xx) -#define PLATFORM_NAME "STM32F769 Very High Performance with DSP and DP FPU" - -#elif defined(STM32F777xx) -#define PLATFORM_NAME "STM32F767 Very High Performance with DSP and DP FPU" - -#elif defined(STM32F779xx) -#define PLATFORM_NAME "STM32F769 Very High Performance with DSP and DP FPU" - -#else -#error "STM32F7xx device not specified" -#endif -/** @} */ - -/** - * @name Sub-family identifier - */ -#if !defined(STM32F7XX) || defined(__DOXYGEN__) -#define STM32F7XX -#endif -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Absolute maximum system clock. - */ -#define STM32_SYSCLK_MAX 216000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 26000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 50000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_BYP_MIN 1000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 2100000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 950000 - -/** - * @brief Maximum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MAX 432000000 - -/** - * @brief Minimum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MIN 192000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 216000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 24000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX / 4) - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2) - -/** - * @brief Maximum SPI/I2S clock frequency. - */ -#define STM32_SPII2S_MAX 54000000 -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 16000000 /**< High speed internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_VOS_SCALE3 (PWR_CR1_VOS_0) -#define STM32_VOS_SCALE2 (PWR_CR1_VOS_1) -#define STM32_VOS_SCALE1 (PWR_CR1_VOS_1 | PWR_CR1_VOS_0) - -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ -#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ -#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ -#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ -#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW mask. */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ -#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ -#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ - -#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ - -#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ -#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ -#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ - -#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */ -#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */ -#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */ -#define STM32_I2SSRC_OFF (1 << 23) /**< ISS clock not required. */ - -#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ -#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ -#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ -#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ -#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ -#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ - -#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ -#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ -#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ -#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ -#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ -#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ - -#define STM32_MCO2SEL_MASK (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. */ -/** @} */ - -/** - * @name RCC_PLLI2SCFGR register bits definitions - * @{ - */ -#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ -#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ -/** @} */ - -/** - * @name RCC_DCKCFGR1 register bits definitions - * @{ - */ -#define STM32_PLLSAIDIVR_MASK (3 << 16) /**< PLLSAIDIVR mask. */ -#define STM32_PLLSAIDIVR_DIV2 (0 << 16) /**< LCD_CLK is R divided by 2. */ -#define STM32_PLLSAIDIVR_DIV4 (1 << 16) /**< LCD_CLK is R divided by 4. */ -#define STM32_PLLSAIDIVR_DIV8 (2 << 16) /**< LCD_CLK is R divided by 8. */ -#define STM32_PLLSAIDIVR_DIV16 (3 << 16) /**< LCD_CLK is R divided by 16.*/ - -#define STM32_SAI1SEL_MASK (3 << 20) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_SAIPLL (0 << 20) /**< SAI1 source is SAIPLL. */ -#define STM32_SAI1SEL_I2SPLL (1 << 20) /**< SAI1 source is I2SPLL. */ -#define STM32_SAI1SEL_CKIN (2 << 20) /**< SAI1 source is I2S_CKIN. */ -#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ - -#define STM32_SAI2SEL_MASK (3 << 22) /**< SAI2SEL mask. */ -#define STM32_SAI2SEL_SAIPLL (0 << 22) /**< SAI2 source is SAIPLL. */ -#define STM32_SAI2SEL_I2SPLL (1 << 22) /**< SAI2 source is I2SPLL. */ -#define STM32_SAI2SEL_CKIN (2 << 22) /**< SAI2 source is I2S_CKIN. */ -#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ - -#define STM32_TIMPRE_MASK (1 << 24) /**< TIMPRE mask. */ -#define STM32_TIMPRE_PCLK (0 << 24) /**< TIM clocks from PCLKx. */ -#define STM32_TIMPRE_HCLK (1 << 24) /**< TIM clocks from HCLK. */ -/** @} */ - -/** - * @name RCC_DCKCFGR2 register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ -#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ -#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ -#define STM32_USART1SEL_HSI (2 << 0) /**< USART1 source is HSI. */ -#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ - -#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ -#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ -#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ -#define STM32_USART2SEL_HSI (2 << 2) /**< USART2 source is HSI. */ -#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ - -#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ -#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ -#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ -#define STM32_USART3SEL_HSI (2 << 4) /**< USART3 source is HSI. */ -#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ - -#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ -#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ -#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ -#define STM32_UART4SEL_HSI (2 << 6) /**< UART4 source is HSI. */ -#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ - -#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ -#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ -#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ -#define STM32_UART5SEL_HSI (2 << 8) /**< UART5 source is HSI. */ -#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ - -#define STM32_USART6SEL_MASK (3 << 10) /**< USART6SEL mask. */ -#define STM32_USART6SEL_PCLK2 (0 << 10) /**< USART6 source is PCLK2. */ -#define STM32_USART6SEL_SYSCLK (1 << 10) /**< USART6 source is SYSCLK. */ -#define STM32_USART6SEL_HSI (2 << 10) /**< USART6 source is HSI. */ -#define STM32_USART6SEL_LSE (3 << 10) /**< USART6 source is LSE. */ - -#define STM32_UART7SEL_MASK (3 << 12) /**< UART7 mask. */ -#define STM32_UART7SEL_PCLK1 (0 << 12) /**< UART7 source is PCLK1. */ -#define STM32_UART7SEL_SYSCLK (1 << 12) /**< UART7 source is SYSCLK. */ -#define STM32_UART7SEL_HSI (2 << 12) /**< UART7 source is HSI. */ -#define STM32_UART7SEL_LSE (3 << 12) /**< UART7 source is LSE. */ - -#define STM32_UART8SEL_MASK (3 << 14) /**< UART8 mask. */ -#define STM32_UART8SEL_PCLK1 (0 << 14) /**< UART8 source is PCLK1. */ -#define STM32_UART8SEL_SYSCLK (1 << 14) /**< UART8 source is SYSCLK. */ -#define STM32_UART8SEL_HSI (2 << 14) /**< UART8 source is HSI. */ -#define STM32_UART8SEL_LSE (3 << 14) /**< UART8 source is LSE. */ - -#define STM32_I2C1SEL_MASK (3 << 16) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK1 (0 << 16) /**< I2C1 source is PCLK1. */ -#define STM32_I2C1SEL_SYSCLK (1 << 16) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI (2 << 16) /**< I2C1 source is HSI. */ -#define STM32_I2C1SEL_LSE (3 << 16) /**< I2C1 source is LSE. */ - -#define STM32_I2C2SEL_MASK (3 << 18) /**< I2C2SEL mask. */ -#define STM32_I2C2SEL_PCLK1 (0 << 18) /**< I2C2 source is PCLK1. */ -#define STM32_I2C2SEL_SYSCLK (1 << 18) /**< I2C2 source is SYSCLK. */ -#define STM32_I2C2SEL_HSI (2 << 18) /**< I2C2 source is HSI. */ -#define STM32_I2C2SEL_LSE (3 << 18) /**< I2C2 source is LSE. */ - -#define STM32_I2C3SEL_MASK (3 << 20) /**< I2C3SEL mask. */ -#define STM32_I2C3SEL_PCLK1 (0 << 20) /**< I2C3 source is PCLK1. */ -#define STM32_I2C3SEL_SYSCLK (1 << 20) /**< I2C3 source is SYSCLK. */ -#define STM32_I2C3SEL_HSI (2 << 20) /**< I2C3 source is HSI. */ -#define STM32_I2C3SEL_LSE (3 << 20) /**< I2C3 source is LSE. */ - -#define STM32_I2C4SEL_MASK (3 << 22) /**< I2C4SEL mask. */ -#define STM32_I2C4SEL_PCLK1 (0 << 22) /**< I2C4 source is PCLK1. */ -#define STM32_I2C4SEL_SYSCLK (1 << 22) /**< I2C4 source is SYSCLK. */ -#define STM32_I2C4SEL_HSI (2 << 22) /**< I2C4 source is HSI. */ -#define STM32_I2C4SEL_LSE (3 << 22) /**< I2C4 source is LSE. */ - -#define STM32_LPTIM1SEL_MASK (3 << 24) /**< LPTIM1SEL mask. */ -#define STM32_LPTIM1SEL_PCLK1 (0 << 24) /**< LPTIM1 source is PCLK1. */ -#define STM32_LPTIM1SEL_LSI (1 << 24) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_HSI (2 << 24) /**< LPTIM1 source is HSI. */ -#define STM32_LPTIM1SEL_LSE (3 << 24) /**< LPTIM1 source is LSE. */ - -#define STM32_CECSEL_MASK (1 << 26) /**< CECSEL mask. */ -#define STM32_CECSEL_LSE (0 << 26) /**< CEC source is LSE. */ -#define STM32_CECSEL_HSIDIV488 (1 << 26) /**< CEC source is HSI/488. */ - -#define STM32_CK48MSEL_MASK (1 << 27) /**< CK48MSEL mask. */ -#define STM32_CK48MSEL_PLL (0 << 27) /**< PLL48CLK source is PLL. */ -#define STM32_CK48MSEL_PLLSAI (1 << 27) /**< PLL48CLK source is PLLSAI. */ - -#define STM32_SDMMC1SEL_MASK (1 << 28) /**< SDMMC1SEL mask. */ -#define STM32_SDMMC1SEL_PLL48CLK (0 << 28) /**< SDMMC1 source is PLL48CLK. */ -#define STM32_SDMMC1SEL_SYSCLK (1 << 28) /**< SDMMC1 source is SYSCLK. */ - -#define STM32_SDMMC2SEL_MASK (1 << 29) /**< SDMMC2SEL mask. */ -#define STM32_SDMMC2SEL_PLL48CLK (0 << 29) /**< SDMMC2 source is PLL48CLK. */ -#define STM32_SDMMC2SEL_SYSCLK (1 << 29) /**< SDMMC2 source is SYSCLK. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables the backup RAM regulator. - */ -#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__) -#define STM32_BKPRAM_ENABLE FALSE -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED TRUE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief USB/SDIO clock setting. - */ -#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) -#define STM32_CLOCK48_REQUIRED TRUE -#endif - -/** - * @brief Main clock source selection. - * @note If the selected clock source is not the PLL then the PLL is not - * initialized and started. - * @note The default value is calculated for a 216MHz system clock from - * an external 25MHz HSE clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @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 216MHz system clock from - * an external 25MHz HSE clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 216MHz system clock from - * an external 25MHz HSE clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 25 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 192..432. - * @note The default value is calculated for a 216MHz system clock from - * an external 25MHz HSE clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 432 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 216MHz system clock from - * an external 25MHz HSE clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 -#endif - -/** - * @brief PLLQ divider value. - * @note The allowed values are 2..15. - * @note The default value is calculated for a 216MHz system clock from - * an external 25MHz HSE clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 9 -#endif - -/** - * @brief AHB prescaler value. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief RTC HSE prescaler value. - * @note The allowed values are 2..31. - */ -#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) -#define STM32_RTCPRE_VALUE 25 -#endif - -/** - * @brief MCO1 clock source value. - * @note The default value outputs HSI clock on MCO1 pin. - */ -#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#endif - -/** - * @brief MCO1 prescaler value. - * @note The default value outputs HSI clock on MCO1 pin. - */ -#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#endif - -/** - * @brief MCO2 clock source value. - * @note The default value outputs SYSCLK / 4 on MCO2 pin. - */ -#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#endif - -/** - * @brief MCO2 prescaler value. - * @note The default value outputs SYSCLK / 4 on MCO2 pin. - */ -#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) -#define STM32_MCO2PRE STM32_MCO2PRE_DIV4 -#endif - -/** - * @brief TIM clock prescaler selection. - */ -#if !defined(STM32_TIMPRE_ENABLE) || defined(__DOXYGEN__) -#define STM32_TIMPRE_ENABLE FALSE -#endif - -/** - * @brief I2S clock source. - */ -#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__) -#define STM32_I2SSRC STM32_I2SSRC_PLLI2S -#endif - -/** - * @brief PLLI2SN multiplier value. - * @note The allowed values are 49..432. - */ -#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SN_VALUE 192 -#endif - -/** - * @brief PLLI2SP divider value. - * @note The allowed values are 2, 4, 6 and 8. - */ -#if !defined(STM32_PLLI2SP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SP_VALUE 4 -#endif - -/** - * @brief PLLI2SQ divider value. - * @note The allowed values are 2..15. - */ -#if !defined(STM32_PLLI2SQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SQ_VALUE 4 -#endif - -/** - * @brief PLLI2SDIVQ divider value (SAI clock divider). - */ -#if !defined(STM32_PLLI2SDIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SDIVQ_VALUE 2 -#endif - -/** - * @brief PLLI2SR divider value. - * @note The allowed values are 2..7. - */ -#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SR_VALUE 4 -#endif - -/** - * @brief PLLSAIN multiplier value. - * @note The allowed values are 49..432. - */ -#if !defined(STM32_PLLSAIN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIN_VALUE 192 -#endif - -/** - * @brief PLLSAIP divider value. - * @note The allowed values are 2, 4, 6 and 8. - */ -#if !defined(STM32_PLLSAIP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIP_VALUE 4 -#endif - -/** - * @brief PLLSAIQ divider value. - * @note The allowed values are 2..15. - */ -#if !defined(STM32_PLLSAIQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIQ_VALUE 4 -#endif - -/** - * @brief PLLSAIR divider value. - * @note The allowed values are 2..7. - */ -#if !defined(STM32_PLLSAIR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIR_VALUE 4 -#endif - -/** - * @brief PLLSAIDIVQ divider value (SAI clock divider). - */ -#if !defined(STM32_PLLSAIDIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIDIVQ_VALUE 2 -#endif - -/** - * @brief PLLSAIDIVR divider value (LCD clock divider). - */ -#if !defined(STM32_PLLSAIDIVR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAIDIVR_VALUE 2 -#endif - -/** - * @brief SAI1SEL value (SAI1 clock source). - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#endif - -/** - * @brief SAI2SEL value (SAI2 clock source). - */ -#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#endif - -/** - * @brief LCD-TFT clock enable switch. - */ -#if !defined(STM32_LCDTFT_REQUIRED) || defined(__DOXYGEN__) -#define STM32_LCDTFT_REQUIRED FALSE -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_PCLK2 -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_PCLK1 -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) -#define STM32_USART3SEL STM32_USART3SEL_PCLK1 -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) -#define STM32_UART4SEL STM32_UART4SEL_PCLK1 -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) -#define STM32_UART5SEL STM32_UART5SEL_PCLK1 -#endif - -/** - * @brief USART6 clock source. - */ -#if !defined(STM32_USART6SEL) || defined(__DOXYGEN__) -#define STM32_USART6SEL STM32_USART6SEL_PCLK2 -#endif - -/** - * @brief UART7 clock source. - */ -#if !defined(STM32_UART7SEL) || defined(__DOXYGEN__) -#define STM32_UART7SEL STM32_UART7SEL_PCLK1 -#endif - -/** - * @brief UART8 clock source. - */ -#if !defined(STM32_UART8SEL) || defined(__DOXYGEN__) -#define STM32_UART8SEL STM32_UART8SEL_PCLK1 -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) -#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 -#endif - -/** - * @brief I2C3 clock source. - */ -#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) -#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 -#endif - -/** - * @brief I2C4 clock source. - */ -#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) -#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#endif - -/** - * @brief CEC clock source. - */ -#if !defined(STM32_CECSEL) || defined(__DOXYGEN__) -#define STM32_CECSEL STM32_CECSEL_LSE -#endif - -/** - * @brief PLL48CLK clock source. - */ -#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) -#define STM32_CK48MSEL STM32_CK48MSEL_PLL -#endif - -/** - * @brief SDMMC1 clock source. - */ -#if !defined(STM32_SDMMC1SEL) || defined(__DOXYGEN__) -#define STM32_SDMMC1SEL STM32_SDMMC1SEL_PLL48CLK -#endif - -/** - * @brief SDMMC2 clock source. - */ -#if !defined(STM32_SDMMC2SEL) || defined(__DOXYGEN__) -#define STM32_SDMMC2SEL STM32_SDMMC2SEL_PLL48CLK -#endif - -/** - * @brief SRAM2 cache-ability. - * @note This setting uses the MPU region 7 if at @p TRUE. - */ -#if !defined(STM32_SRAM2_NOCACHE) || defined(__DOXYGEN__) -#define STM32_SRAM2_NOCACHE FALSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F7xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F7xx_MCUCONF not defined" -#endif - -#if defined(STM32F722xx) && !defined(STM32F722_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F722_MCUCONF not defined" -#endif - -#if defined(STM32F732xx) && !defined(STM32F732_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F732_MCUCONF not defined" -#endif - -#if defined(STM32F723xx) && !defined(STM32F723_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F723_MCUCONF not defined" -#endif - -#if defined(STM32F733xx) && !defined(STM32F733_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F733_MCUCONF not defined" -#endif - -#if defined(STM32F746xx) && !defined(STM32F746_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F746_MCUCONF not defined" -#endif - -#if defined(STM32F756xx) && !defined(STM32F756_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F756_MCUCONF not defined" -#endif - -#if defined(STM32F765xx) && !defined(STM32F765_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F765_MCUCONF not defined" -#endif - -#if defined(STM32F767xx) && !defined(STM32F767_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F767_MCUCONF not defined" -#endif - -#if defined(STM32F777xx) && !defined(STM32F777_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F777_MCUCONF not defined" -#endif - -#if defined(STM32F769xx) && !defined(STM32F769_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F769_MCUCONF not defined" -#endif - -#if defined(STM32F779xx) && !defined(STM32F779_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F779_MCUCONF not defined" -#endif - -/* - * Board file checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif -#if !defined(STM32_VDD) -#error "STM32_VDD not defined in board.h" -#endif - -/** - * @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 120000000 -#define STM32_4WS_THRESHOLD 150000000 -#define STM32_5WS_THRESHOLD 180000000 -#define STM32_6WS_THRESHOLD 210000000 -#define STM32_7WS_THRESHOLD STM32_SYSCLK_MAX -#define STM32_8WS_THRESHOLD 0 -#define STM32_9WS_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 192000000 -#define STM32_8WS_THRESHOLD STM32_SYSCLK_MAX -#define STM32_9WS_THRESHOLD 0 - -#elif (STM32_VDD >= 210) && (STM32_VDD < 240) -#define STM32_0WS_THRESHOLD 22000000 -#define STM32_1WS_THRESHOLD 44000000 -#define STM32_2WS_THRESHOLD 66000000 -#define STM32_3WS_THRESHOLD 88000000 -#define STM32_4WS_THRESHOLD 110000000 -#define STM32_5WS_THRESHOLD 132000000 -#define STM32_6WS_THRESHOLD 154000000 -#define STM32_7WS_THRESHOLD 176000000 -#define STM32_8WS_THRESHOLD 198000000 -#define STM32_9WS_THRESHOLD STM32_SYSCLK_MAX - -#elif (STM32_VDD >= 180) && (STM32_VDD < 210) -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 120000000 -#define STM32_6WS_THRESHOLD 140000000 -#define STM32_7WS_THRESHOLD 160000000 -#define STM32_8WS_THRESHOLD 180000000 -#define STM32_9WS_THRESHOLD 0 - -#else -#error "invalid VDD voltage specified" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_I2SSRC" -#endif - -#if ((STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SAI1SEL" -#endif - -#if ((STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SAI2SEL" -#endif - -#if STM32_LCDTFT_REQUIRED && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_LCDTFT_REQUIRED" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#else /* STM32_HSECLK != 0 */ -#if defined(STM32_HSE_BYPASS) -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_BYP_MAX)" -#endif -#else /* !defined(STM32_HSE_BYPASS) */ -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif -#endif /* !defined(STM32_HSE_BYPASS) */ -#endif /* STM32_HSECLK != 0 */ -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ - ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_I2SSRC" -#endif - -#if ((STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL) | \ - (STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SAI1SEL" -#endif - -#if ((STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL) | \ - (STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SAI2SEL" -#endif - -#if STM32_LCDTFT_REQUIRED && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_LCDTFT_REQUIRED" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#if STM32_MCO1SEL == STM32_MCO1SEL_LSE -#error "LSE not enabled, required by STM32_MCO1SEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 2) && (STM32_PLLM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLLM (STM32_PLLM_VALUE << 0) -#else -#error "invalid STM32_PLLM_VALUE value specified" -#endif - -/** - * @brief PLLs input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PLLM_VALUE) - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLLs input frequency range check. - */ -#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_CLOCK48_REQUIRED && (STM32_CK48MSEL == STM32_CK48MSEL_PLL)) || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ - (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 6) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLP (0 << 16) - -#elif STM32_PLLP_VALUE == 4 -#define STM32_PLLP (1 << 16) - -#elif STM32_PLLP_VALUE == 6 -#define STM32_PLLP (2 << 16) - -#elif STM32_PLLP_VALUE == 8 -#define STM32_PLLP (3 << 16) - -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL P output clock frequency. - */ -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) - -/** - * @brief PLL Q output clock frequency. - */ -#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) - -/* - * PLL output frequency range check. - */ -#if (STM32_PLL_P_CLKOUT < STM32_PLLOUT_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_HSICLK - -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK - -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK - -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLL_P_CLKOUT - -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/* Calculating VOS settings.*/ -#if STM32_SYSCLK <= 144000000 -#define STM32_VOS STM32_VOS_SCALE3 -#define STM32_OVERDRIVE_REQUIRED FALSE - -#elif STM32_SYSCLK <= 168000000 -#define STM32_VOS STM32_VOS_SCALE2 -#define STM32_OVERDRIVE_REQUIRED FALSE - -#elif STM32_SYSCLK <= 180000000 -#define STM32_VOS STM32_VOS_SCALE1 -#define STM32_OVERDRIVE_REQUIRED FALSE - -#else -#define STM32_VOS STM32_VOS_SCALE1 -#define STM32_OVERDRIVE_REQUIRED TRUE -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) - -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) - -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) - -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) - -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) - -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) - -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) - -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) - -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) - -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/* - * PLLI2S enable check. - */ -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLLI2S activation flag. - */ -#define STM32_ACTIVATE_PLLI2S TRUE -#else -#define STM32_ACTIVATE_PLLI2S FALSE -#endif - -/** - * @brief STM32_PLLI2SN field. - */ -#if ((STM32_PLLI2SN_VALUE >= 49) && (STM32_PLLI2SN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) -#else -#error "invalid STM32_PLLI2SN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SQ field. - */ -#if ((STM32_PLLI2SQ_VALUE >= 2) && (STM32_PLLI2SQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SQ (STM32_PLLI2SQ_VALUE << 24) -#else -#error "invalid STM32_PLLI2SQ_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 STM32_PLLI2SP field. - */ -#if (STM32_PLLI2SP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLI2SP (0 << 16) - -#elif STM32_PLLI2SP_VALUE == 4 -#define STM32_PLLI2SP (1 << 16) - -#elif STM32_PLLI2SP_VALUE == 6 -#define STM32_PLLI2SP (2 << 16) - -#elif STM32_PLLI2SP_VALUE == 8 -#define STM32_PLLI2SP (3 << 16) - -#else -#error "invalid STM32_PLLI2SP_VALUE value specified" -#endif - -/** - * @brief PLLI2S 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 P output clock frequency. - */ -#define STM32_PLLI2S_P_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SP_VALUE) - -/** - * @brief PLLI2S Q output clock frequency. - */ -#define STM32_PLLI2S_Q_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SQ_VALUE) - -/** - * @brief PLLI2S R output clock frequency. - */ -#define STM32_PLLI2S_R_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) - -/** - * @brief STM32_PLLI2SDIVQ field. - */ -#if (STM32_PLLI2SDIVQ_VALUE < 1) || (STM32_PLLI2SDIVQ_VALUE > 32) -#error "STM32_PLLI2SDIVQ_VALUE out of acceptable range" -#endif -#define STM32_PLLI2SDIVQ ((STM32_PLLI2SDIVQ_VALUE - 1) << 0) - -/** - * @brief PLLI2S Q output clock frequency after divisor. - */ -#define STM32_PLLI2SDIVQ_CLKOUT (STM32_PLLI2S_Q_CLKOUT / STM32_PLLI2SDIVQ_VALUE) - -/* - * PLLSAI enable check. - */ -#if (STM32_CLOCK48_REQUIRED && (STM32_CK48MSEL == STM32_CK48MSEL_PLLSAI)) | \ - STM32_LCDTFT_REQUIRED || \ - (STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLLSAI activation flag. - */ -#define STM32_ACTIVATE_PLLSAI TRUE -#else -#define STM32_ACTIVATE_PLLSAI FALSE -#endif - -/** - * @brief STM32_PLLSAIN field. - */ -#if ((STM32_PLLSAIN_VALUE >= 49) && (STM32_PLLSAIN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIN (STM32_PLLSAIN_VALUE << 6) -#else -#error "invalid STM32_PLLSAIN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIQ field. - */ -#if ((STM32_PLLSAIQ_VALUE >= 2) && (STM32_PLLSAIQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIQ (STM32_PLLSAIQ_VALUE << 24) -#else -#error "invalid STM32_PLLSAIR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIR field. - */ -#if ((STM32_PLLSAIR_VALUE >= 2) && (STM32_PLLSAIR_VALUE <= 7)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAIR (STM32_PLLSAIR_VALUE << 28) -#else -#error "invalid STM32_PLLSAIR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAIP field. - */ -#if (STM32_PLLSAIP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAIP (0 << 16) - -#elif STM32_PLLSAIP_VALUE == 4 -#define STM32_PLLSAIP (1 << 16) - -#elif STM32_PLLSAIP_VALUE == 6 -#define STM32_PLLSAIP (2 << 16) - -#elif STM32_PLLSAIP_VALUE == 8 -#define STM32_PLLSAIP (3 << 16) - -#else -#error "invalid STM32_PLLSAIP_VALUE value specified" -#endif - -/** - * @brief PLLSAI VCO frequency. - */ -#define STM32_PLLSAIVCO (STM32_PLLCLKIN * STM32_PLLSAIN_VALUE) - -/* - * PLLSAI VCO frequency range check. - */ -#if (STM32_PLLSAIVCO < STM32_PLLVCO_MIN) || \ - (STM32_PLLSAIVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLSAIVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI P output clock frequency. - */ -#define STM32_PLLSAI_P_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIP_VALUE) - -/** - * @brief PLLSAI Q output clock frequency. - */ -#define STM32_PLLSAI_Q_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIQ_VALUE) - -/** - * @brief PLLSAI R output clock frequency. - */ -#define STM32_PLLSAI_R_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIR_VALUE) - -/** - * @brief STM32_PLLSAIDIVQ field. - */ -#if (STM32_PLLSAIDIVQ_VALUE < 1) || (STM32_PLLSAIDIVQ_VALUE > 32) -#error "STM32_PLLSAIDIVQ_VALUE out of acceptable range" -#endif -#define STM32_PLLSAIDIVQ ((STM32_PLLSAIDIVQ_VALUE - 1) << 8) - -/** - * @brief PLLSAI Q output clock frequency after divisor. - */ -#define STM32_PLLSAIDIVQ_CLKOUT (STM32_PLLSAI_Q_CLKOUT / STM32_PLLSAIDIVQ_VALUE) - -/* - * STM32_PLLSAIDIVR field. - */ -#if (STM32_PLLSAIDIVR_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAIDIVR (0 << 16) - -#elif STM32_PLLSAIDIVR_VALUE == 4 -#define STM32_PLLSAIDIVR (1 << 16) - -#elif STM32_PLLSAIDIVR_VALUE == 8 -#define STM32_PLLSAIDIVR (2 << 16) - -#elif STM32_PLLSAIDIVR_VALUE == 16 -#define STM32_PLLSAIDIVR (3 << 16) - -#else -#error "invalid STM32_PLLSAIDIVR_VALUE value specified" -#endif - -/** - * @brief PLLSAI R output clock frequency after divisor. - */ -#define STM32_PLLSAIDIVR_CLKOUT (STM32_PLLSAI_R_CLKOUT / STM32_PLLSAIDIVR_VALUE) - -/** - * @brief MCO1 divider clock. - */ -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__) -#define STM32_MCO1DIVCLK STM32_HSICLK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE -#define STM32_MCO1DIVCLK STM32_LSECLK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE -#define STM32_MCO1DIVCLK STM32_HSECLK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL -#define STM32_MCO1DIVCLK STM32_PLL_P_CLKOUT - -#else -#error "invalid STM32_MCO1SEL value specified" -#endif - -/** - * @brief MCO1 output pin clock. - */ -#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCO1CLK STM32_MCO1DIVCLK - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2) - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3) - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4) - -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5) - -#else -#error "invalid STM32_MCO1PRE value specified" -#endif - -/** - * @brief MCO2 divider clock. - */ -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__) -#define STM32_MCO2DIVCLK STM32_HSECLK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL -#define STM32_MCO2DIVCLK STM32_PLL_P_CLKOUT - -#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK -#define STM32_MCO2DIVCLK STM32_SYSCLK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S -#define STM32_MCO2DIVCLK STM32_PLLI2S - -#else -#error "invalid STM32_MCO2SEL value specified" -#endif - -/** - * @brief MCO2 output pin clock. - */ -#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCO2CLK STM32_MCO2DIVCLK - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2) - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3) - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4) - -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5) - -#else -#error "invalid STM32_MCO2PRE value specified" -#endif - -/** - * @brief RTC HSE divider setting. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief HSE divider toward RTC clock. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK STM32_HSEDIVCLK - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK2 -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SEL == STM32_USART1SEL_HSI -#define STM32_USART1CLK STM32_HSICLK -#elif STM32_USART1SEL == STM32_USART1SEL_LSE -#define STM32_USART1CLK STM32_LSECLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK1 -#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SEL == STM32_USART2SEL_HSI -#define STM32_USART2CLK STM32_HSICLK -#elif STM32_USART2SEL == STM32_USART2SEL_LSE -#define STM32_USART2CLK STM32_LSECLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 frequency. - */ -#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART3CLK STM32_PCLK1 -#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK -#elif STM32_USART3SEL == STM32_USART3SEL_HSI -#define STM32_USART3CLK STM32_HSICLK -#elif STM32_USART3SEL == STM32_USART3SEL_LSE -#define STM32_USART3CLK STM32_LSECLK -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief UART4 frequency. - */ -#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART4CLK STM32_PCLK1 -#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK -#elif STM32_UART4SEL == STM32_UART4SEL_HSI -#define STM32_UART4CLK STM32_HSICLK -#elif STM32_UART4SEL == STM32_UART4SEL_LSE -#define STM32_UART4CLK STM32_LSECLK -#else -#error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 frequency. - */ -#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART5CLK STM32_PCLK1 -#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK -#elif STM32_UART5SEL == STM32_UART5SEL_HSI -#define STM32_UART5CLK STM32_HSICLK -#elif STM32_UART5SEL == STM32_UART5SEL_LSE -#define STM32_UART5CLK STM32_LSECLK -#else -#error "invalid source selected for UART5 clock" -#endif - -/** - * @brief USART6 frequency. - */ -#if (STM32_USART6SEL == STM32_USART6SEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_USART6CLK STM32_PCLK2 -#elif STM32_USART6SEL == STM32_USART6SEL_SYSCLK -#define STM32_USART6CLK STM32_SYSCLK -#elif STM32_USART6SEL == STM32_USART6SEL_HSI -#define STM32_USART6CLK STM32_HSICLK -#elif STM32_USART6SEL == STM32_USART6SEL_LSE -#define STM32_USART6CLK STM32_LSECLK -#else -#error "invalid source selected for USART6 clock" -#endif - -/** - * @brief UART7 frequency. - */ -#if (STM32_UART7SEL == STM32_UART7SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART7CLK STM32_PCLK1 -#elif STM32_UART7SEL == STM32_UART7SEL_SYSCLK -#define STM32_UART7CLK STM32_SYSCLK -#elif STM32_UART7SEL == STM32_UART7SEL_HSI -#define STM32_UART7CLK STM32_HSICLK -#elif STM32_UART7SEL == STM32_UART7SEL_LSE -#define STM32_UART7CLK STM32_LSECLK -#else -#error "invalid source selected for UART7 clock" -#endif - -/** - * @brief UART8 frequency. - */ -#if (STM32_UART8SEL == STM32_UART8SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART8CLK STM32_PCLK1 -#elif STM32_UART8SEL == STM32_UART8SEL_SYSCLK -#define STM32_UART8CLK STM32_SYSCLK -#elif STM32_UART8SEL == STM32_UART8SEL_HSI -#define STM32_UART8CLK STM32_HSICLK -#elif STM32_UART8SEL == STM32_UART8SEL_LSE -#define STM32_UART8CLK STM32_LSECLK -#else -#error "invalid source selected for UART8 clock" -#endif - -/** - * @brief I2C1 frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK1 -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI -#define STM32_I2C1CLK STM32_HSICLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 frequency. - */ -#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C2CLK STM32_PCLK1 -#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK -#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI -#define STM32_I2C2CLK STM32_HSICLK -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief I2C3 frequency. - */ -#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C3CLK STM32_PCLK1 -#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK -#define STM32_I2C3CLK STM32_SYSCLK -#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI -#define STM32_I2C3CLK STM32_HSICLK -#else -#error "invalid source selected for I2C3 clock" -#endif - -/** - * @brief I2C4 frequency. - */ -#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C4CLK STM32_PCLK1 -#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK -#define STM32_I2C4CLK STM32_SYSCLK -#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI -#define STM32_I2C4CLK STM32_HSICLK -#else -#error "invalid source selected for I2C4 clock" -#endif - -/** - * @brief LPTIM1 frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK1 -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI -#define STM32_LPTIM1CLK STM32_LSICLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI -#define STM32_LPTIM1CLK STM32_HSICLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE -#define STM32_LPTIM1CLK STM32_LSECLK -#else -#error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief 48MHz frequency. - */ -#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) -#if (STM32_CK48MSEL == STM32_CK48MSEL_PLL) || defined(__DOXYGEN__) -#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) -#elif STM32_CK48MSEL == STM32_CK48MSEL_PLLSAI -#define STM32_PLL48CLK (STM32_PLLSAIVCO / STM32_PLLSAIP_VALUE) -#else -#error "invalid source selected for PLL48CLK clock" -#endif -#else /* !STM32_CLOCK48_REQUIRED */ -#define STM32_PLL48CLK 0 -#endif /* !STM32_CLOCK48_REQUIRED */ - -/** - * @brief I2S frequency. - */ -#if (STM32_I2SSRC == STM32_I2SSRC_OFF) || defined(__DOXYGEN__) -#define STM32_I2SCLK 0 -#elif STM32_I2SSRC == STM32_I2SSRC_CKIN -#define STM32_I2SCLK 0 /* Unknown, would require a board value */ -#elif STM32_I2SSRC == STM32_I2SSRC_PLLI2S -#define STM32_I2SCLK STM32_PLLI2S_R_CLKOUT -#else -#error "invalid source selected for I2S clock" -#endif - -/** - * @brief SAI1 frequency. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_OFF) || defined(__DOXYGEN__) -#define STM32_SAI1CLK 0 -#elif STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL -#define STM32_SAI1CLK STM32_PLLSAIDIVQ_CLKOUT -#elif STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL -#define STM32_SAI1CLK STM32_PLLI2SDIVQ_CLKOUT -#elif STM32_SAI1SEL == STM32_SAI1SEL_CKIN -#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ -#else -#error "invalid source selected for SAI1 clock" -#endif - -/** - * @brief SAI2 frequency. - */ -#if (STM32_SAI2SEL == STM32_SAI2SEL_OFF) || defined(__DOXYGEN__) -#define STM32_SAI2CLK 0 -#elif STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL -#define STM32_SAI2CLK STM32_PLLSAIDIVQ_CLKOUT -#elif STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL -#define STM32_SAI2CLK STM32_PLLI2SDIVQ_CLKOUT -#elif STM32_SAI2SEL == STM32_SAI2SEL_CKIN -#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ -#else -#error "invalid source selected for SAI2 clock" -#endif - -/** - * @brief SDMMC1 frequency. - */ -#if (STM32_SDMMC1SEL == STM32_SDMMC1SEL_PLL48CLK) || defined(__DOXYGEN__) -#define STM32_SDMMC1CLK STM32_PLL48CLK -#elif STM32_SDMMC1SEL == STM32_SDMMC1SEL_SYSCLK -#define STM32_SDMMC1CLK STM32_SYSCLK -#else -#error "invalid source selected for SDMMC1 clock" -#endif - -/** - * @brief SDMMC2 frequency. - */ -#if (STM32_SDMMC2SEL == STM32_SDMMC2SEL_PLL48CLK) || defined(__DOXYGEN__) -#define STM32_SDMMC2CLK STM32_PLL48CLK -#elif STM32_SDMMC2SEL == STM32_SDMMC2SEL_SYSCLK -#define STM32_SDMMC2CLK STM32_SYSCLK -#else -#error "invalid source selected for SDMMC2 clock" -#endif - -/** - * @brief Clock of timers connected to APB1 - */ -#if (STM32_TIMPRE_ENABLE == FALSE) || defined(__DOXYGEN__) -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif -#else -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || \ - (STM32_PPRE1 == STM32_PPRE1_DIV2) || \ - (STM32_PPRE1 == STM32_PPRE1_DIV4) -#define STM32_TIMCLK1 (STM32_HCLK * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 4) -#endif -#endif - -/** - * @brief Clock of timers connected to APB2. - */ -#if (STM32_TIMPRE_ENABLE == FALSE) || defined(__DOXYGEN__) -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif -#else -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || \ - (STM32_PPRE2 == STM32_PPRE2_DIV2) || \ - (STM32_PPRE2 == STM32_PPRE2_DIV4) -#define STM32_TIMCLK2 (STM32_HCLK * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 4) -#endif -#endif - -/** - * @brief RNG clock point. - */ -#define STM32_RNGCLK STM32_PLL48CLK - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000000 - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS 0x00000001 - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS 0x00000002 - -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS 0x00000003 - -#elif STM32_HCLK <= STM32_4WS_THRESHOLD -#define STM32_FLASHBITS 0x00000004 - -#elif STM32_HCLK <= STM32_5WS_THRESHOLD -#define STM32_FLASHBITS 0x00000005 - -#elif STM32_HCLK <= STM32_6WS_THRESHOLD -#define STM32_FLASHBITS 0x00000006 - -#elif STM32_HCLK <= STM32_7WS_THRESHOLD -#define STM32_FLASHBITS 0x00000007 - -#elif STM32_HCLK <= STM32_8WS_THRESHOLD -#define STM32_FLASHBITS 0x00000008 - -#elif STM32_HCLK <= STM32_9WS_THRESHOLD -#define STM32_FLASHBITS 0x00000009 - -#else -#error "invalid frequency at specified VDD level" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/hal_lld.h + * @brief STM32F7xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * - STM32_VDD (as hundredths of Volt). + * . + * One of the following macros must also be defined: + * - STM32F722xx, STM32F723xx very high-performance MCUs. + * - STM32F732xx, STM32F733xx very high-performance MCUs. + * - STM32F745xx, STM32F746xx, STM32F756xx very high-performance MCUs. + * - STM32F765xx, STM32F767xx, STM32F769xx very high-performance MCUs. + * - STM32F777xx, STM32F779xx very high-performance MCUs. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +#define HAL_IMPLEMENTS_COUNTERS TRUE + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32F722xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" + +#elif defined(STM32F723xx) +#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" + +#elif defined(STM32F732xx) +#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" + +#elif defined(STM32F733xx) +#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" + +#elif defined(STM32F745xx) +#define PLATFORM_NAME "STM32F745 Very High Performance with DSP and FPU" + +#elif defined(STM32F746xx) +#define PLATFORM_NAME "STM32F746 Very High Performance with DSP and FPU" + +#elif defined(STM32F756xx) +#define PLATFORM_NAME "STM32F756 Very High Performance with DSP and FPU" + +#elif defined(STM32F765xx) +#define PLATFORM_NAME "STM32F767 Very High Performance with DSP and DP FPU" + +#elif defined(STM32F767xx) +#define PLATFORM_NAME "STM32F767 Very High Performance with DSP and DP FPU" + +#elif defined(STM32F769xx) +#define PLATFORM_NAME "STM32F769 Very High Performance with DSP and DP FPU" + +#elif defined(STM32F777xx) +#define PLATFORM_NAME "STM32F767 Very High Performance with DSP and DP FPU" + +#elif defined(STM32F779xx) +#define PLATFORM_NAME "STM32F769 Very High Performance with DSP and DP FPU" + +#else +#error "STM32F7xx device not specified" +#endif +/** @} */ + +/** + * @name Sub-family identifier + */ +#if !defined(STM32F7XX) || defined(__DOXYGEN__) +#define STM32F7XX +#endif +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Absolute maximum system clock. + */ +#define STM32_SYSCLK_MAX 216000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 26000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 50000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_BYP_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 2100000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 950000 + +/** + * @brief Maximum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MAX 432000000 + +/** + * @brief Minimum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MIN 192000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 216000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 24000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX / 4) + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2) + +/** + * @brief Maximum SPI/I2S clock frequency. + */ +#define STM32_SPII2S_MAX 54000000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 16000000 /**< High speed internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_VOS_SCALE3 (PWR_CR1_VOS_0) +#define STM32_VOS_SCALE2 (PWR_CR1_VOS_1) +#define STM32_VOS_SCALE1 (PWR_CR1_VOS_1 | PWR_CR1_VOS_0) + +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ +#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ +#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ +#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ +#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW mask. */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ +#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ +#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ + +#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ + +#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ +#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ +#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ + +#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */ +#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */ +#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */ +#define STM32_I2SSRC_OFF (1 << 23) /**< ISS clock not required. */ + +#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ +#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ +#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ +#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ +#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ +#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ + +#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ +#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ +#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ +#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ +#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ +#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ + +#define STM32_MCO2SEL_MASK (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. */ +/** @} */ + +/** + * @name RCC_PLLI2SCFGR register bits definitions + * @{ + */ +#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ +#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ +/** @} */ + +/** + * @name RCC_DCKCFGR1 register bits definitions + * @{ + */ +#define STM32_PLLSAIDIVR_MASK (3 << 16) /**< PLLSAIDIVR mask. */ +#define STM32_PLLSAIDIVR_DIV2 (0 << 16) /**< LCD_CLK is R divided by 2. */ +#define STM32_PLLSAIDIVR_DIV4 (1 << 16) /**< LCD_CLK is R divided by 4. */ +#define STM32_PLLSAIDIVR_DIV8 (2 << 16) /**< LCD_CLK is R divided by 8. */ +#define STM32_PLLSAIDIVR_DIV16 (3 << 16) /**< LCD_CLK is R divided by 16.*/ + +#define STM32_SAI1SEL_MASK (3 << 20) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_SAIPLL (0 << 20) /**< SAI1 source is SAIPLL. */ +#define STM32_SAI1SEL_I2SPLL (1 << 20) /**< SAI1 source is I2SPLL. */ +#define STM32_SAI1SEL_CKIN (2 << 20) /**< SAI1 source is I2S_CKIN. */ +#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ + +#define STM32_SAI2SEL_MASK (3 << 22) /**< SAI2SEL mask. */ +#define STM32_SAI2SEL_SAIPLL (0 << 22) /**< SAI2 source is SAIPLL. */ +#define STM32_SAI2SEL_I2SPLL (1 << 22) /**< SAI2 source is I2SPLL. */ +#define STM32_SAI2SEL_CKIN (2 << 22) /**< SAI2 source is I2S_CKIN. */ +#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ + +#define STM32_TIMPRE_MASK (1 << 24) /**< TIMPRE mask. */ +#define STM32_TIMPRE_PCLK (0 << 24) /**< TIM clocks from PCLKx. */ +#define STM32_TIMPRE_HCLK (1 << 24) /**< TIM clocks from HCLK. */ +/** @} */ + +/** + * @name RCC_DCKCFGR2 register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ +#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ +#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ +#define STM32_USART1SEL_HSI (2 << 0) /**< USART1 source is HSI. */ +#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ + +#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ +#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ +#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ +#define STM32_USART2SEL_HSI (2 << 2) /**< USART2 source is HSI. */ +#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ + +#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ +#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ +#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ +#define STM32_USART3SEL_HSI (2 << 4) /**< USART3 source is HSI. */ +#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ + +#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ +#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ +#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ +#define STM32_UART4SEL_HSI (2 << 6) /**< UART4 source is HSI. */ +#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ + +#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ +#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ +#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ +#define STM32_UART5SEL_HSI (2 << 8) /**< UART5 source is HSI. */ +#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ + +#define STM32_USART6SEL_MASK (3 << 10) /**< USART6SEL mask. */ +#define STM32_USART6SEL_PCLK2 (0 << 10) /**< USART6 source is PCLK2. */ +#define STM32_USART6SEL_SYSCLK (1 << 10) /**< USART6 source is SYSCLK. */ +#define STM32_USART6SEL_HSI (2 << 10) /**< USART6 source is HSI. */ +#define STM32_USART6SEL_LSE (3 << 10) /**< USART6 source is LSE. */ + +#define STM32_UART7SEL_MASK (3 << 12) /**< UART7 mask. */ +#define STM32_UART7SEL_PCLK1 (0 << 12) /**< UART7 source is PCLK1. */ +#define STM32_UART7SEL_SYSCLK (1 << 12) /**< UART7 source is SYSCLK. */ +#define STM32_UART7SEL_HSI (2 << 12) /**< UART7 source is HSI. */ +#define STM32_UART7SEL_LSE (3 << 12) /**< UART7 source is LSE. */ + +#define STM32_UART8SEL_MASK (3 << 14) /**< UART8 mask. */ +#define STM32_UART8SEL_PCLK1 (0 << 14) /**< UART8 source is PCLK1. */ +#define STM32_UART8SEL_SYSCLK (1 << 14) /**< UART8 source is SYSCLK. */ +#define STM32_UART8SEL_HSI (2 << 14) /**< UART8 source is HSI. */ +#define STM32_UART8SEL_LSE (3 << 14) /**< UART8 source is LSE. */ + +#define STM32_I2C1SEL_MASK (3 << 16) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK1 (0 << 16) /**< I2C1 source is PCLK1. */ +#define STM32_I2C1SEL_SYSCLK (1 << 16) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI (2 << 16) /**< I2C1 source is HSI. */ +#define STM32_I2C1SEL_LSE (3 << 16) /**< I2C1 source is LSE. */ + +#define STM32_I2C2SEL_MASK (3 << 18) /**< I2C2SEL mask. */ +#define STM32_I2C2SEL_PCLK1 (0 << 18) /**< I2C2 source is PCLK1. */ +#define STM32_I2C2SEL_SYSCLK (1 << 18) /**< I2C2 source is SYSCLK. */ +#define STM32_I2C2SEL_HSI (2 << 18) /**< I2C2 source is HSI. */ +#define STM32_I2C2SEL_LSE (3 << 18) /**< I2C2 source is LSE. */ + +#define STM32_I2C3SEL_MASK (3 << 20) /**< I2C3SEL mask. */ +#define STM32_I2C3SEL_PCLK1 (0 << 20) /**< I2C3 source is PCLK1. */ +#define STM32_I2C3SEL_SYSCLK (1 << 20) /**< I2C3 source is SYSCLK. */ +#define STM32_I2C3SEL_HSI (2 << 20) /**< I2C3 source is HSI. */ +#define STM32_I2C3SEL_LSE (3 << 20) /**< I2C3 source is LSE. */ + +#define STM32_I2C4SEL_MASK (3 << 22) /**< I2C4SEL mask. */ +#define STM32_I2C4SEL_PCLK1 (0 << 22) /**< I2C4 source is PCLK1. */ +#define STM32_I2C4SEL_SYSCLK (1 << 22) /**< I2C4 source is SYSCLK. */ +#define STM32_I2C4SEL_HSI (2 << 22) /**< I2C4 source is HSI. */ +#define STM32_I2C4SEL_LSE (3 << 22) /**< I2C4 source is LSE. */ + +#define STM32_LPTIM1SEL_MASK (3 << 24) /**< LPTIM1SEL mask. */ +#define STM32_LPTIM1SEL_PCLK1 (0 << 24) /**< LPTIM1 source is PCLK1. */ +#define STM32_LPTIM1SEL_LSI (1 << 24) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_HSI (2 << 24) /**< LPTIM1 source is HSI. */ +#define STM32_LPTIM1SEL_LSE (3 << 24) /**< LPTIM1 source is LSE. */ + +#define STM32_CECSEL_MASK (1 << 26) /**< CECSEL mask. */ +#define STM32_CECSEL_LSE (0 << 26) /**< CEC source is LSE. */ +#define STM32_CECSEL_HSIDIV488 (1 << 26) /**< CEC source is HSI/488. */ + +#define STM32_CK48MSEL_MASK (1 << 27) /**< CK48MSEL mask. */ +#define STM32_CK48MSEL_PLL (0 << 27) /**< PLL48CLK source is PLL. */ +#define STM32_CK48MSEL_PLLSAI (1 << 27) /**< PLL48CLK source is PLLSAI. */ + +#define STM32_SDMMC1SEL_MASK (1 << 28) /**< SDMMC1SEL mask. */ +#define STM32_SDMMC1SEL_PLL48CLK (0 << 28) /**< SDMMC1 source is PLL48CLK. */ +#define STM32_SDMMC1SEL_SYSCLK (1 << 28) /**< SDMMC1 source is SYSCLK. */ + +#define STM32_SDMMC2SEL_MASK (1 << 29) /**< SDMMC2SEL mask. */ +#define STM32_SDMMC2SEL_PLL48CLK (0 << 29) /**< SDMMC2 source is PLL48CLK. */ +#define STM32_SDMMC2SEL_SYSCLK (1 << 29) /**< SDMMC2 source is SYSCLK. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables the backup RAM regulator. + */ +#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__) +#define STM32_BKPRAM_ENABLE FALSE +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED TRUE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief USB/SDIO clock setting. + */ +#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) +#define STM32_CLOCK48_REQUIRED TRUE +#endif + +/** + * @brief Main clock source selection. + * @note If the selected clock source is not the PLL then the PLL is not + * initialized and started. + * @note The default value is calculated for a 216MHz system clock from + * an external 25MHz HSE clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @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 216MHz system clock from + * an external 25MHz HSE clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 216MHz system clock from + * an external 25MHz HSE clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 25 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 192..432. + * @note The default value is calculated for a 216MHz system clock from + * an external 25MHz HSE clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 432 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 216MHz system clock from + * an external 25MHz HSE clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 2 +#endif + +/** + * @brief PLLQ divider value. + * @note The allowed values are 2..15. + * @note The default value is calculated for a 216MHz system clock from + * an external 25MHz HSE clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 9 +#endif + +/** + * @brief AHB prescaler value. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief RTC HSE prescaler value. + * @note The allowed values are 2..31. + */ +#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) +#define STM32_RTCPRE_VALUE 25 +#endif + +/** + * @brief MCO1 clock source value. + * @note The default value outputs HSI clock on MCO1 pin. + */ +#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#endif + +/** + * @brief MCO1 prescaler value. + * @note The default value outputs HSI clock on MCO1 pin. + */ +#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#endif + +/** + * @brief MCO2 clock source value. + * @note The default value outputs SYSCLK / 4 on MCO2 pin. + */ +#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#endif + +/** + * @brief MCO2 prescaler value. + * @note The default value outputs SYSCLK / 4 on MCO2 pin. + */ +#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) +#define STM32_MCO2PRE STM32_MCO2PRE_DIV4 +#endif + +/** + * @brief TIM clock prescaler selection. + */ +#if !defined(STM32_TIMPRE_ENABLE) || defined(__DOXYGEN__) +#define STM32_TIMPRE_ENABLE FALSE +#endif + +/** + * @brief I2S clock source. + */ +#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__) +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#endif + +/** + * @brief PLLI2SN multiplier value. + * @note The allowed values are 49..432. + */ +#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SN_VALUE 192 +#endif + +/** + * @brief PLLI2SP divider value. + * @note The allowed values are 2, 4, 6 and 8. + */ +#if !defined(STM32_PLLI2SP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SP_VALUE 4 +#endif + +/** + * @brief PLLI2SQ divider value. + * @note The allowed values are 2..15. + */ +#if !defined(STM32_PLLI2SQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SQ_VALUE 4 +#endif + +/** + * @brief PLLI2SDIVQ divider value (SAI clock divider). + */ +#if !defined(STM32_PLLI2SDIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SDIVQ_VALUE 2 +#endif + +/** + * @brief PLLI2SR divider value. + * @note The allowed values are 2..7. + */ +#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SR_VALUE 4 +#endif + +/** + * @brief PLLSAIN multiplier value. + * @note The allowed values are 49..432. + */ +#if !defined(STM32_PLLSAIN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIN_VALUE 192 +#endif + +/** + * @brief PLLSAIP divider value. + * @note The allowed values are 2, 4, 6 and 8. + */ +#if !defined(STM32_PLLSAIP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIP_VALUE 4 +#endif + +/** + * @brief PLLSAIQ divider value. + * @note The allowed values are 2..15. + */ +#if !defined(STM32_PLLSAIQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIQ_VALUE 4 +#endif + +/** + * @brief PLLSAIR divider value. + * @note The allowed values are 2..7. + */ +#if !defined(STM32_PLLSAIR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIR_VALUE 4 +#endif + +/** + * @brief PLLSAIDIVQ divider value (SAI clock divider). + */ +#if !defined(STM32_PLLSAIDIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIDIVQ_VALUE 2 +#endif + +/** + * @brief PLLSAIDIVR divider value (LCD clock divider). + */ +#if !defined(STM32_PLLSAIDIVR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAIDIVR_VALUE 2 +#endif + +/** + * @brief SAI1SEL value (SAI1 clock source). + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#endif + +/** + * @brief SAI2SEL value (SAI2 clock source). + */ +#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#endif + +/** + * @brief LCD-TFT clock enable switch. + */ +#if !defined(STM32_LCDTFT_REQUIRED) || defined(__DOXYGEN__) +#define STM32_LCDTFT_REQUIRED FALSE +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_PCLK2 +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_PCLK1 +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) +#define STM32_USART3SEL STM32_USART3SEL_PCLK1 +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) +#define STM32_UART4SEL STM32_UART4SEL_PCLK1 +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) +#define STM32_UART5SEL STM32_UART5SEL_PCLK1 +#endif + +/** + * @brief USART6 clock source. + */ +#if !defined(STM32_USART6SEL) || defined(__DOXYGEN__) +#define STM32_USART6SEL STM32_USART6SEL_PCLK2 +#endif + +/** + * @brief UART7 clock source. + */ +#if !defined(STM32_UART7SEL) || defined(__DOXYGEN__) +#define STM32_UART7SEL STM32_UART7SEL_PCLK1 +#endif + +/** + * @brief UART8 clock source. + */ +#if !defined(STM32_UART8SEL) || defined(__DOXYGEN__) +#define STM32_UART8SEL STM32_UART8SEL_PCLK1 +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#endif + +/** + * @brief I2C3 clock source. + */ +#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#endif + +/** + * @brief I2C4 clock source. + */ +#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#endif + +/** + * @brief CEC clock source. + */ +#if !defined(STM32_CECSEL) || defined(__DOXYGEN__) +#define STM32_CECSEL STM32_CECSEL_LSE +#endif + +/** + * @brief PLL48CLK clock source. + */ +#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#endif + +/** + * @brief SDMMC1 clock source. + */ +#if !defined(STM32_SDMMC1SEL) || defined(__DOXYGEN__) +#define STM32_SDMMC1SEL STM32_SDMMC1SEL_PLL48CLK +#endif + +/** + * @brief SDMMC2 clock source. + */ +#if !defined(STM32_SDMMC2SEL) || defined(__DOXYGEN__) +#define STM32_SDMMC2SEL STM32_SDMMC2SEL_PLL48CLK +#endif + +/** + * @brief SRAM2 cache-ability. + * @note This setting uses the MPU region 7 if at @p TRUE. + */ +#if !defined(STM32_SRAM2_NOCACHE) || defined(__DOXYGEN__) +#define STM32_SRAM2_NOCACHE FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F7xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F7xx_MCUCONF not defined" +#endif + +#if defined(STM32F722xx) && !defined(STM32F722_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F722_MCUCONF not defined" +#endif + +#if defined(STM32F732xx) && !defined(STM32F732_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F732_MCUCONF not defined" +#endif + +#if defined(STM32F723xx) && !defined(STM32F723_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F723_MCUCONF not defined" +#endif + +#if defined(STM32F733xx) && !defined(STM32F733_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F733_MCUCONF not defined" +#endif + +#if defined(STM32F746xx) && !defined(STM32F746_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F746_MCUCONF not defined" +#endif + +#if defined(STM32F756xx) && !defined(STM32F756_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F756_MCUCONF not defined" +#endif + +#if defined(STM32F765xx) && !defined(STM32F765_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F765_MCUCONF not defined" +#endif + +#if defined(STM32F767xx) && !defined(STM32F767_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F767_MCUCONF not defined" +#endif + +#if defined(STM32F777xx) && !defined(STM32F777_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F777_MCUCONF not defined" +#endif + +#if defined(STM32F769xx) && !defined(STM32F769_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F769_MCUCONF not defined" +#endif + +#if defined(STM32F779xx) && !defined(STM32F779_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F779_MCUCONF not defined" +#endif + +/* + * Board file checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif +#if !defined(STM32_VDD) +#error "STM32_VDD not defined in board.h" +#endif + +/** + * @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 120000000 +#define STM32_4WS_THRESHOLD 150000000 +#define STM32_5WS_THRESHOLD 180000000 +#define STM32_6WS_THRESHOLD 210000000 +#define STM32_7WS_THRESHOLD STM32_SYSCLK_MAX +#define STM32_8WS_THRESHOLD 0 +#define STM32_9WS_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 192000000 +#define STM32_8WS_THRESHOLD STM32_SYSCLK_MAX +#define STM32_9WS_THRESHOLD 0 + +#elif (STM32_VDD >= 210) && (STM32_VDD < 240) +#define STM32_0WS_THRESHOLD 22000000 +#define STM32_1WS_THRESHOLD 44000000 +#define STM32_2WS_THRESHOLD 66000000 +#define STM32_3WS_THRESHOLD 88000000 +#define STM32_4WS_THRESHOLD 110000000 +#define STM32_5WS_THRESHOLD 132000000 +#define STM32_6WS_THRESHOLD 154000000 +#define STM32_7WS_THRESHOLD 176000000 +#define STM32_8WS_THRESHOLD 198000000 +#define STM32_9WS_THRESHOLD STM32_SYSCLK_MAX + +#elif (STM32_VDD >= 180) && (STM32_VDD < 210) +#define STM32_0WS_THRESHOLD 20000000 +#define STM32_1WS_THRESHOLD 40000000 +#define STM32_2WS_THRESHOLD 60000000 +#define STM32_3WS_THRESHOLD 80000000 +#define STM32_4WS_THRESHOLD 100000000 +#define STM32_5WS_THRESHOLD 120000000 +#define STM32_6WS_THRESHOLD 140000000 +#define STM32_7WS_THRESHOLD 160000000 +#define STM32_8WS_THRESHOLD 180000000 +#define STM32_9WS_THRESHOLD 0 + +#else +#error "invalid VDD voltage specified" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_I2SSRC" +#endif + +#if ((STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SAI1SEL" +#endif + +#if ((STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SAI2SEL" +#endif + +#if STM32_LCDTFT_REQUIRED && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_LCDTFT_REQUIRED" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#else /* STM32_HSECLK != 0 */ +#if defined(STM32_HSE_BYPASS) +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_BYP_MAX)" +#endif +#else /* !defined(STM32_HSE_BYPASS) */ +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif +#endif /* !defined(STM32_HSE_BYPASS) */ +#endif /* STM32_HSECLK != 0 */ +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ + ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_I2SSRC" +#endif + +#if ((STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL) | \ + (STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SAI1SEL" +#endif + +#if ((STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL) | \ + (STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SAI2SEL" +#endif + +#if STM32_LCDTFT_REQUIRED && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_LCDTFT_REQUIRED" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#if STM32_MCO1SEL == STM32_MCO1SEL_LSE +#error "LSE not enabled, required by STM32_MCO1SEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 2) && (STM32_PLLM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLLM (STM32_PLLM_VALUE << 0) +#else +#error "invalid STM32_PLLM_VALUE value specified" +#endif + +/** + * @brief PLLs input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PLLM_VALUE) + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLLs input frequency range check. + */ +#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_CLOCK48_REQUIRED && (STM32_CK48MSEL == STM32_CK48MSEL_PLL)) || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ + (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 6) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLP (0 << 16) + +#elif STM32_PLLP_VALUE == 4 +#define STM32_PLLP (1 << 16) + +#elif STM32_PLLP_VALUE == 6 +#define STM32_PLLP (2 << 16) + +#elif STM32_PLLP_VALUE == 8 +#define STM32_PLLP (3 << 16) + +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL P output clock frequency. + */ +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) + +/** + * @brief PLL Q output clock frequency. + */ +#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) + +/* + * PLL output frequency range check. + */ +#if (STM32_PLL_P_CLKOUT < STM32_PLLOUT_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_HSICLK + +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK + +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK + +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLL_P_CLKOUT + +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/* Calculating VOS settings.*/ +#if STM32_SYSCLK <= 144000000 +#define STM32_VOS STM32_VOS_SCALE3 +#define STM32_OVERDRIVE_REQUIRED FALSE + +#elif STM32_SYSCLK <= 168000000 +#define STM32_VOS STM32_VOS_SCALE2 +#define STM32_OVERDRIVE_REQUIRED FALSE + +#elif STM32_SYSCLK <= 180000000 +#define STM32_VOS STM32_VOS_SCALE1 +#define STM32_OVERDRIVE_REQUIRED FALSE + +#else +#define STM32_VOS STM32_VOS_SCALE1 +#define STM32_OVERDRIVE_REQUIRED TRUE +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) + +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) + +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) + +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) + +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) + +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) + +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) + +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) + +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) + +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/* + * PLLI2S enable check. + */ +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLLI2S activation flag. + */ +#define STM32_ACTIVATE_PLLI2S TRUE +#else +#define STM32_ACTIVATE_PLLI2S FALSE +#endif + +/** + * @brief STM32_PLLI2SN field. + */ +#if ((STM32_PLLI2SN_VALUE >= 49) && (STM32_PLLI2SN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) +#else +#error "invalid STM32_PLLI2SN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SQ field. + */ +#if ((STM32_PLLI2SQ_VALUE >= 2) && (STM32_PLLI2SQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SQ (STM32_PLLI2SQ_VALUE << 24) +#else +#error "invalid STM32_PLLI2SQ_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 STM32_PLLI2SP field. + */ +#if (STM32_PLLI2SP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLI2SP (0 << 16) + +#elif STM32_PLLI2SP_VALUE == 4 +#define STM32_PLLI2SP (1 << 16) + +#elif STM32_PLLI2SP_VALUE == 6 +#define STM32_PLLI2SP (2 << 16) + +#elif STM32_PLLI2SP_VALUE == 8 +#define STM32_PLLI2SP (3 << 16) + +#else +#error "invalid STM32_PLLI2SP_VALUE value specified" +#endif + +/** + * @brief PLLI2S 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 P output clock frequency. + */ +#define STM32_PLLI2S_P_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SP_VALUE) + +/** + * @brief PLLI2S Q output clock frequency. + */ +#define STM32_PLLI2S_Q_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SQ_VALUE) + +/** + * @brief PLLI2S R output clock frequency. + */ +#define STM32_PLLI2S_R_CLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) + +/** + * @brief STM32_PLLI2SDIVQ field. + */ +#if (STM32_PLLI2SDIVQ_VALUE < 1) || (STM32_PLLI2SDIVQ_VALUE > 32) +#error "STM32_PLLI2SDIVQ_VALUE out of acceptable range" +#endif +#define STM32_PLLI2SDIVQ ((STM32_PLLI2SDIVQ_VALUE - 1) << 0) + +/** + * @brief PLLI2S Q output clock frequency after divisor. + */ +#define STM32_PLLI2SDIVQ_CLKOUT (STM32_PLLI2S_Q_CLKOUT / STM32_PLLI2SDIVQ_VALUE) + +/* + * PLLSAI enable check. + */ +#if (STM32_CLOCK48_REQUIRED && (STM32_CK48MSEL == STM32_CK48MSEL_PLLSAI)) | \ + STM32_LCDTFT_REQUIRED || \ + (STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLLSAI activation flag. + */ +#define STM32_ACTIVATE_PLLSAI TRUE +#else +#define STM32_ACTIVATE_PLLSAI FALSE +#endif + +/** + * @brief STM32_PLLSAIN field. + */ +#if ((STM32_PLLSAIN_VALUE >= 49) && (STM32_PLLSAIN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIN (STM32_PLLSAIN_VALUE << 6) +#else +#error "invalid STM32_PLLSAIN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIQ field. + */ +#if ((STM32_PLLSAIQ_VALUE >= 2) && (STM32_PLLSAIQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIQ (STM32_PLLSAIQ_VALUE << 24) +#else +#error "invalid STM32_PLLSAIR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIR field. + */ +#if ((STM32_PLLSAIR_VALUE >= 2) && (STM32_PLLSAIR_VALUE <= 7)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAIR (STM32_PLLSAIR_VALUE << 28) +#else +#error "invalid STM32_PLLSAIR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAIP field. + */ +#if (STM32_PLLSAIP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAIP (0 << 16) + +#elif STM32_PLLSAIP_VALUE == 4 +#define STM32_PLLSAIP (1 << 16) + +#elif STM32_PLLSAIP_VALUE == 6 +#define STM32_PLLSAIP (2 << 16) + +#elif STM32_PLLSAIP_VALUE == 8 +#define STM32_PLLSAIP (3 << 16) + +#else +#error "invalid STM32_PLLSAIP_VALUE value specified" +#endif + +/** + * @brief PLLSAI VCO frequency. + */ +#define STM32_PLLSAIVCO (STM32_PLLCLKIN * STM32_PLLSAIN_VALUE) + +/* + * PLLSAI VCO frequency range check. + */ +#if (STM32_PLLSAIVCO < STM32_PLLVCO_MIN) || \ + (STM32_PLLSAIVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLSAIVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI P output clock frequency. + */ +#define STM32_PLLSAI_P_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIP_VALUE) + +/** + * @brief PLLSAI Q output clock frequency. + */ +#define STM32_PLLSAI_Q_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIQ_VALUE) + +/** + * @brief PLLSAI R output clock frequency. + */ +#define STM32_PLLSAI_R_CLKOUT (STM32_PLLSAIVCO / STM32_PLLSAIR_VALUE) + +/** + * @brief STM32_PLLSAIDIVQ field. + */ +#if (STM32_PLLSAIDIVQ_VALUE < 1) || (STM32_PLLSAIDIVQ_VALUE > 32) +#error "STM32_PLLSAIDIVQ_VALUE out of acceptable range" +#endif +#define STM32_PLLSAIDIVQ ((STM32_PLLSAIDIVQ_VALUE - 1) << 8) + +/** + * @brief PLLSAI Q output clock frequency after divisor. + */ +#define STM32_PLLSAIDIVQ_CLKOUT (STM32_PLLSAI_Q_CLKOUT / STM32_PLLSAIDIVQ_VALUE) + +/* + * STM32_PLLSAIDIVR field. + */ +#if (STM32_PLLSAIDIVR_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAIDIVR (0 << 16) + +#elif STM32_PLLSAIDIVR_VALUE == 4 +#define STM32_PLLSAIDIVR (1 << 16) + +#elif STM32_PLLSAIDIVR_VALUE == 8 +#define STM32_PLLSAIDIVR (2 << 16) + +#elif STM32_PLLSAIDIVR_VALUE == 16 +#define STM32_PLLSAIDIVR (3 << 16) + +#else +#error "invalid STM32_PLLSAIDIVR_VALUE value specified" +#endif + +/** + * @brief PLLSAI R output clock frequency after divisor. + */ +#define STM32_PLLSAIDIVR_CLKOUT (STM32_PLLSAI_R_CLKOUT / STM32_PLLSAIDIVR_VALUE) + +/** + * @brief MCO1 divider clock. + */ +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__) +#define STM32_MCO1DIVCLK STM32_HSICLK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE +#define STM32_MCO1DIVCLK STM32_LSECLK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE +#define STM32_MCO1DIVCLK STM32_HSECLK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL +#define STM32_MCO1DIVCLK STM32_PLL_P_CLKOUT + +#else +#error "invalid STM32_MCO1SEL value specified" +#endif + +/** + * @brief MCO1 output pin clock. + */ +#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCO1CLK STM32_MCO1DIVCLK + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2) + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3) + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4) + +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5) + +#else +#error "invalid STM32_MCO1PRE value specified" +#endif + +/** + * @brief MCO2 divider clock. + */ +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__) +#define STM32_MCO2DIVCLK STM32_HSECLK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL +#define STM32_MCO2DIVCLK STM32_PLL_P_CLKOUT + +#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK +#define STM32_MCO2DIVCLK STM32_SYSCLK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S +#define STM32_MCO2DIVCLK STM32_PLLI2S + +#else +#error "invalid STM32_MCO2SEL value specified" +#endif + +/** + * @brief MCO2 output pin clock. + */ +#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCO2CLK STM32_MCO2DIVCLK + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2) + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3) + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4) + +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5) + +#else +#error "invalid STM32_MCO2PRE value specified" +#endif + +/** + * @brief RTC HSE divider setting. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief HSE divider toward RTC clock. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK STM32_HSEDIVCLK + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK2 +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SEL == STM32_USART1SEL_HSI +#define STM32_USART1CLK STM32_HSICLK +#elif STM32_USART1SEL == STM32_USART1SEL_LSE +#define STM32_USART1CLK STM32_LSECLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART2CLK STM32_PCLK1 +#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SEL == STM32_USART2SEL_HSI +#define STM32_USART2CLK STM32_HSICLK +#elif STM32_USART2SEL == STM32_USART2SEL_LSE +#define STM32_USART2CLK STM32_LSECLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 frequency. + */ +#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART3CLK STM32_PCLK1 +#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK +#elif STM32_USART3SEL == STM32_USART3SEL_HSI +#define STM32_USART3CLK STM32_HSICLK +#elif STM32_USART3SEL == STM32_USART3SEL_LSE +#define STM32_USART3CLK STM32_LSECLK +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief UART4 frequency. + */ +#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART4CLK STM32_PCLK1 +#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK +#define STM32_UART4CLK STM32_SYSCLK +#elif STM32_UART4SEL == STM32_UART4SEL_HSI +#define STM32_UART4CLK STM32_HSICLK +#elif STM32_UART4SEL == STM32_UART4SEL_LSE +#define STM32_UART4CLK STM32_LSECLK +#else +#error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 frequency. + */ +#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART5CLK STM32_PCLK1 +#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK +#define STM32_UART5CLK STM32_SYSCLK +#elif STM32_UART5SEL == STM32_UART5SEL_HSI +#define STM32_UART5CLK STM32_HSICLK +#elif STM32_UART5SEL == STM32_UART5SEL_LSE +#define STM32_UART5CLK STM32_LSECLK +#else +#error "invalid source selected for UART5 clock" +#endif + +/** + * @brief USART6 frequency. + */ +#if (STM32_USART6SEL == STM32_USART6SEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_USART6CLK STM32_PCLK2 +#elif STM32_USART6SEL == STM32_USART6SEL_SYSCLK +#define STM32_USART6CLK STM32_SYSCLK +#elif STM32_USART6SEL == STM32_USART6SEL_HSI +#define STM32_USART6CLK STM32_HSICLK +#elif STM32_USART6SEL == STM32_USART6SEL_LSE +#define STM32_USART6CLK STM32_LSECLK +#else +#error "invalid source selected for USART6 clock" +#endif + +/** + * @brief UART7 frequency. + */ +#if (STM32_UART7SEL == STM32_UART7SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART7CLK STM32_PCLK1 +#elif STM32_UART7SEL == STM32_UART7SEL_SYSCLK +#define STM32_UART7CLK STM32_SYSCLK +#elif STM32_UART7SEL == STM32_UART7SEL_HSI +#define STM32_UART7CLK STM32_HSICLK +#elif STM32_UART7SEL == STM32_UART7SEL_LSE +#define STM32_UART7CLK STM32_LSECLK +#else +#error "invalid source selected for UART7 clock" +#endif + +/** + * @brief UART8 frequency. + */ +#if (STM32_UART8SEL == STM32_UART8SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART8CLK STM32_PCLK1 +#elif STM32_UART8SEL == STM32_UART8SEL_SYSCLK +#define STM32_UART8CLK STM32_SYSCLK +#elif STM32_UART8SEL == STM32_UART8SEL_HSI +#define STM32_UART8CLK STM32_HSICLK +#elif STM32_UART8SEL == STM32_UART8SEL_LSE +#define STM32_UART8CLK STM32_LSECLK +#else +#error "invalid source selected for UART8 clock" +#endif + +/** + * @brief I2C1 frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_PCLK1 +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI +#define STM32_I2C1CLK STM32_HSICLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 frequency. + */ +#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C2CLK STM32_PCLK1 +#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK +#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI +#define STM32_I2C2CLK STM32_HSICLK +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief I2C3 frequency. + */ +#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C3CLK STM32_PCLK1 +#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK +#define STM32_I2C3CLK STM32_SYSCLK +#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI +#define STM32_I2C3CLK STM32_HSICLK +#else +#error "invalid source selected for I2C3 clock" +#endif + +/** + * @brief I2C4 frequency. + */ +#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C4CLK STM32_PCLK1 +#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK +#define STM32_I2C4CLK STM32_SYSCLK +#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI +#define STM32_I2C4CLK STM32_HSICLK +#else +#error "invalid source selected for I2C4 clock" +#endif + +/** + * @brief LPTIM1 frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM1CLK STM32_PCLK1 +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI +#define STM32_LPTIM1CLK STM32_LSICLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI +#define STM32_LPTIM1CLK STM32_HSICLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE +#define STM32_LPTIM1CLK STM32_LSECLK +#else +#error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief 48MHz frequency. + */ +#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) +#if (STM32_CK48MSEL == STM32_CK48MSEL_PLL) || defined(__DOXYGEN__) +#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) +#elif STM32_CK48MSEL == STM32_CK48MSEL_PLLSAI +#define STM32_PLL48CLK (STM32_PLLSAIVCO / STM32_PLLSAIP_VALUE) +#else +#error "invalid source selected for PLL48CLK clock" +#endif +#else /* !STM32_CLOCK48_REQUIRED */ +#define STM32_PLL48CLK 0 +#endif /* !STM32_CLOCK48_REQUIRED */ + +/** + * @brief I2S frequency. + */ +#if (STM32_I2SSRC == STM32_I2SSRC_OFF) || defined(__DOXYGEN__) +#define STM32_I2SCLK 0 +#elif STM32_I2SSRC == STM32_I2SSRC_CKIN +#define STM32_I2SCLK 0 /* Unknown, would require a board value */ +#elif STM32_I2SSRC == STM32_I2SSRC_PLLI2S +#define STM32_I2SCLK STM32_PLLI2S_R_CLKOUT +#else +#error "invalid source selected for I2S clock" +#endif + +/** + * @brief SAI1 frequency. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_OFF) || defined(__DOXYGEN__) +#define STM32_SAI1CLK 0 +#elif STM32_SAI1SEL == STM32_SAI1SEL_SAIPLL +#define STM32_SAI1CLK STM32_PLLSAIDIVQ_CLKOUT +#elif STM32_SAI1SEL == STM32_SAI1SEL_I2SPLL +#define STM32_SAI1CLK STM32_PLLI2SDIVQ_CLKOUT +#elif STM32_SAI1SEL == STM32_SAI1SEL_CKIN +#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ +#else +#error "invalid source selected for SAI1 clock" +#endif + +/** + * @brief SAI2 frequency. + */ +#if (STM32_SAI2SEL == STM32_SAI2SEL_OFF) || defined(__DOXYGEN__) +#define STM32_SAI2CLK 0 +#elif STM32_SAI2SEL == STM32_SAI2SEL_SAIPLL +#define STM32_SAI2CLK STM32_PLLSAIDIVQ_CLKOUT +#elif STM32_SAI2SEL == STM32_SAI2SEL_I2SPLL +#define STM32_SAI2CLK STM32_PLLI2SDIVQ_CLKOUT +#elif STM32_SAI2SEL == STM32_SAI2SEL_CKIN +#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ +#else +#error "invalid source selected for SAI2 clock" +#endif + +/** + * @brief SDMMC1 frequency. + */ +#if (STM32_SDMMC1SEL == STM32_SDMMC1SEL_PLL48CLK) || defined(__DOXYGEN__) +#define STM32_SDMMC1CLK STM32_PLL48CLK +#elif STM32_SDMMC1SEL == STM32_SDMMC1SEL_SYSCLK +#define STM32_SDMMC1CLK STM32_SYSCLK +#else +#error "invalid source selected for SDMMC1 clock" +#endif + +/** + * @brief SDMMC2 frequency. + */ +#if (STM32_SDMMC2SEL == STM32_SDMMC2SEL_PLL48CLK) || defined(__DOXYGEN__) +#define STM32_SDMMC2CLK STM32_PLL48CLK +#elif STM32_SDMMC2SEL == STM32_SDMMC2SEL_SYSCLK +#define STM32_SDMMC2CLK STM32_SYSCLK +#else +#error "invalid source selected for SDMMC2 clock" +#endif + +/** + * @brief Clock of timers connected to APB1 + */ +#if (STM32_TIMPRE_ENABLE == FALSE) || defined(__DOXYGEN__) +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif +#else +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || \ + (STM32_PPRE1 == STM32_PPRE1_DIV2) || \ + (STM32_PPRE1 == STM32_PPRE1_DIV4) +#define STM32_TIMCLK1 (STM32_HCLK * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 4) +#endif +#endif + +/** + * @brief Clock of timers connected to APB2. + */ +#if (STM32_TIMPRE_ENABLE == FALSE) || defined(__DOXYGEN__) +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif +#else +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || \ + (STM32_PPRE2 == STM32_PPRE2_DIV2) || \ + (STM32_PPRE2 == STM32_PPRE2_DIV4) +#define STM32_TIMCLK2 (STM32_HCLK * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 4) +#endif +#endif + +/** + * @brief RNG clock point. + */ +#define STM32_RNGCLK STM32_PLL48CLK + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000000 + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS 0x00000001 + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS 0x00000002 + +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS 0x00000003 + +#elif STM32_HCLK <= STM32_4WS_THRESHOLD +#define STM32_FLASHBITS 0x00000004 + +#elif STM32_HCLK <= STM32_5WS_THRESHOLD +#define STM32_FLASHBITS 0x00000005 + +#elif STM32_HCLK <= STM32_6WS_THRESHOLD +#define STM32_FLASHBITS 0x00000006 + +#elif STM32_HCLK <= STM32_7WS_THRESHOLD +#define STM32_FLASHBITS 0x00000007 + +#elif STM32_HCLK <= STM32_8WS_THRESHOLD +#define STM32_FLASHBITS 0x00000008 + +#elif STM32_HCLK <= STM32_9WS_THRESHOLD +#define STM32_FLASHBITS 0x00000009 + +#else +#error "invalid frequency at specified VDD level" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F7xx/platform.mk b/os/hal/ports/STM32/STM32F7xx/platform.mk index cf89bb6c5b..f65bc14487 100644 --- a/os/hal/ports/STM32/STM32F7xx/platform.mk +++ b/os/hal/ports/STM32/STM32F7xx/platform.mk @@ -1,49 +1,49 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F7xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F7xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32F7xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F7xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F7xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32F7xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32F7xx/stm32_isr.c b/os/hal/ports/STM32/STM32F7xx/stm32_isr.c index f895a57264..1fd78d5f4b 100644 --- a/os/hal/ports/STM32/STM32F7xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32F7xx/stm32_isr.c @@ -1,176 +1,176 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/stm32_isr.c - * @brief STM32F7xx ISR handler code. - * - * @addtogroup STM32F7xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_exti0.inc" -#include "stm32_exti1.inc" -#include "stm32_exti2.inc" -#include "stm32_exti3.inc" -#include "stm32_exti4.inc" -#include "stm32_exti5_9.inc" -#include "stm32_exti10_15.inc" -#include "stm32_exti16.inc" -#include "stm32_exti17.inc" -#include "stm32_exti18.inc" -#include "stm32_exti19.inc" -#include "stm32_exti20.inc" -#include "stm32_exti21.inc" -#include "stm32_exti22.inc" -#include "stm32_exti23.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart3.inc" -#include "stm32_uart4.inc" -#include "stm32_uart5.inc" -#include "stm32_usart6.inc" -#include "stm32_uart7.inc" -#include "stm32_uart8.inc" - -#include "stm32_tim1_9_10_11.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim4.inc" -#include "stm32_tim5.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim8_12_13_14.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_irq_init(); - exti1_irq_init(); - exti2_irq_init(); - exti3_irq_init(); - exti4_irq_init(); - exti5_9_irq_init(); - exti10_15_irq_init(); - exti16_irq_init(); - exti17_irq_init(); - exti18_irq_init(); - exti19_irq_init(); - exti20_irq_init(); - exti21_irq_init(); - exti22_irq_init(); - exti23_irq_init(); - - tim1_tim9_tim10_tim11_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim4_irq_init(); - tim5_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim8_tim12_tim13_tim14_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_irq_init(); - uart4_irq_init(); - uart5_irq_init(); - usart6_irq_init(); - uart7_irq_init(); - uart8_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_irq_deinit(); - exti1_irq_deinit(); - exti2_irq_deinit(); - exti3_irq_deinit(); - exti4_irq_deinit(); - exti5_9_irq_deinit(); - exti10_15_irq_deinit(); - exti16_irq_deinit(); - exti17_irq_deinit(); - exti18_irq_deinit(); - exti19_irq_deinit(); - exti20_irq_deinit(); - exti21_irq_deinit(); - exti22_irq_deinit(); - exti23_irq_deinit(); - - tim1_tim9_tim10_tim11_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim4_irq_deinit(); - tim5_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim8_tim12_tim13_tim14_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_irq_deinit(); - uart4_irq_deinit(); - uart5_irq_deinit(); - usart6_irq_deinit(); - uart7_irq_deinit(); - uart8_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/stm32_isr.c + * @brief STM32F7xx ISR handler code. + * + * @addtogroup STM32F7xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_exti0.inc" +#include "stm32_exti1.inc" +#include "stm32_exti2.inc" +#include "stm32_exti3.inc" +#include "stm32_exti4.inc" +#include "stm32_exti5_9.inc" +#include "stm32_exti10_15.inc" +#include "stm32_exti16.inc" +#include "stm32_exti17.inc" +#include "stm32_exti18.inc" +#include "stm32_exti19.inc" +#include "stm32_exti20.inc" +#include "stm32_exti21.inc" +#include "stm32_exti22.inc" +#include "stm32_exti23.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart3.inc" +#include "stm32_uart4.inc" +#include "stm32_uart5.inc" +#include "stm32_usart6.inc" +#include "stm32_uart7.inc" +#include "stm32_uart8.inc" + +#include "stm32_tim1_9_10_11.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim4.inc" +#include "stm32_tim5.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim8_12_13_14.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_irq_init(); + exti1_irq_init(); + exti2_irq_init(); + exti3_irq_init(); + exti4_irq_init(); + exti5_9_irq_init(); + exti10_15_irq_init(); + exti16_irq_init(); + exti17_irq_init(); + exti18_irq_init(); + exti19_irq_init(); + exti20_irq_init(); + exti21_irq_init(); + exti22_irq_init(); + exti23_irq_init(); + + tim1_tim9_tim10_tim11_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim4_irq_init(); + tim5_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim8_tim12_tim13_tim14_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_irq_init(); + uart4_irq_init(); + uart5_irq_init(); + usart6_irq_init(); + uart7_irq_init(); + uart8_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_irq_deinit(); + exti1_irq_deinit(); + exti2_irq_deinit(); + exti3_irq_deinit(); + exti4_irq_deinit(); + exti5_9_irq_deinit(); + exti10_15_irq_deinit(); + exti16_irq_deinit(); + exti17_irq_deinit(); + exti18_irq_deinit(); + exti19_irq_deinit(); + exti20_irq_deinit(); + exti21_irq_deinit(); + exti22_irq_deinit(); + exti23_irq_deinit(); + + tim1_tim9_tim10_tim11_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim4_irq_deinit(); + tim5_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim8_tim12_tim13_tim14_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_irq_deinit(); + uart4_irq_deinit(); + uart5_irq_deinit(); + usart6_irq_deinit(); + uart7_irq_deinit(); + uart8_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F7xx/stm32_isr.h b/os/hal/ports/STM32/STM32F7xx/stm32_isr.h index 5b9c222f83..1ed43c388a 100644 --- a/os/hal/ports/STM32/STM32F7xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32F7xx/stm32_isr.h @@ -1,340 +1,340 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/stm32_isr.h - * @brief STM32F7xx ISR handler header. - * - * @addtogroup STM32F7xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM8_SUPPRESS_ISR -#define STM32_TIM9_SUPPRESS_ISR -#define STM32_TIM10_SUPPRESS_ISR -#define STM32_TIM11_SUPPRESS_ISR -#define STM32_TIM12_SUPPRESS_ISR -#define STM32_TIM13_SUPPRESS_ISR -#define STM32_TIM14_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_USART6_SUPPRESS_ISR -#define STM32_UART7_SUPPRESS_ISR -#define STM32_UART8_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC units. - */ -#define STM32_ADC_HANDLER Vector88 - -#define STM32_ADC_NUMBER 18 - -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 -#define STM32_CAN2_TX_HANDLER Vector13C -#define STM32_CAN2_RX0_HANDLER Vector140 -#define STM32_CAN2_RX1_HANDLER Vector144 -#define STM32_CAN2_SCE_HANDLER Vector148 -#define STM32_CAN3_TX_HANDLER Vector1E0 -#define STM32_CAN3_RX0_HANDLER Vector1E4 -#define STM32_CAN3_RX1_HANDLER Vector1E8 -#define STM32_CAN3_SCE_HANDLER Vector1EC - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 -#define STM32_CAN2_TX_NUMBER 63 -#define STM32_CAN2_RX0_NUMBER 64 -#define STM32_CAN2_RX1_NUMBER 65 -#define STM32_CAN2_SCE_NUMBER 66 -#define STM32_CAN3_TX_NUMBER 104 -#define STM32_CAN3_RX0_NUMBER 105 -#define STM32_CAN3_RX1_NUMBER 106 -#define STM32_CAN3_SCE_NUMBER 107 - -/* - * DMA units. - */ -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 - -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* - * EXTI unit. - */ -#define STM32_EXTI0_HANDLER Vector58 -#define STM32_EXTI1_HANDLER Vector5C -#define STM32_EXTI2_HANDLER Vector60 -#define STM32_EXTI3_HANDLER Vector64 -#define STM32_EXTI4_HANDLER Vector68 -#define STM32_EXTI5_9_HANDLER Vector9C -#define STM32_EXTI10_15_HANDLER VectorE0 -#define STM32_EXTI16_HANDLER Vector44 /* PVD */ -#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */ -#define STM32_EXTI18_HANDLER VectorE8 /* USB FS WAKEUP */ -#define STM32_EXTI19_HANDLER Vector138 /* ETH WAKEUP */ -#define STM32_EXTI20_HANDLER Vector170 /* USB HS WAKEUP */ -#define STM32_EXTI21_HANDLER Vector48 /* RTC TAMPER */ -#define STM32_EXTI22_HANDLER Vector4C /* RTC WAKEUP */ -#define STM32_EXTI23_HANDLER Vector1B4 /* LPTIM1 */ - -#define STM32_EXTI0_NUMBER 6 -#define STM32_EXTI1_NUMBER 7 -#define STM32_EXTI2_NUMBER 8 -#define STM32_EXTI3_NUMBER 9 -#define STM32_EXTI4_NUMBER 10 -#define STM32_EXTI5_9_NUMBER 23 -#define STM32_EXTI10_15_NUMBER 40 -#define STM32_EXTI16_NUMBER 1 -#define STM32_EXTI17_NUMBER 41 -#define STM32_EXTI18_NUMBER 42 -#define STM32_EXTI19_NUMBER 62 -#define STM32_EXTI20_NUMBER 76 -#define STM32_EXTI21_NUMBER 2 -#define STM32_EXTI22_NUMBER 3 -#define STM32_EXTI23_NUMBER 93 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C3_EVENT_HANDLER Vector160 -#define STM32_I2C3_ERROR_HANDLER Vector164 -#define STM32_I2C4_EVENT_HANDLER Vector1BC -#define STM32_I2C4_ERROR_HANDLER Vector1C0 - -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 -#define STM32_I2C3_EVENT_NUMBER 72 -#define STM32_I2C3_ERROR_NUMBER 73 -#define STM32_I2C4_EVENT_NUMBER 95 -#define STM32_I2C4_ERROR_NUMBER 96 - -/* - * ETH units. - */ -#define STM32_ETH_HANDLER Vector134 - -#define STM32_ETH_NUMBER 61 - -/* - * QUADSPI units. - */ -#define STM32_QUADSPI1_HANDLER Vector1B0 - -#define STM32_QUADSPI1_NUMBER 92 - -/* - * SDMMC units. - */ -#define STM32_SDMMC1_HANDLER Vector104 -#define STM32_SDMMC2_HANDLER Vector1DC - -#define STM32_SDMMC1_NUMBER 49 -#define STM32_SDMMC2_NUMBER 103 - -/* - * TIM units. - */ -#define STM32_TIM1_BRK_TIM9_HANDLER VectorA0 -#define STM32_TIM1_UP_TIM10_HANDLER VectorA4 -#define STM32_TIM1_TRGCO_TIM11_HANDLER VectorA8 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_BRK_TIM12_HANDLER VectorEC -#define STM32_TIM8_UP_TIM13_HANDLER VectorF0 -#define STM32_TIM8_TRGCO_TIM14_HANDLER VectorF4 -#define STM32_TIM8_CC_HANDLER VectorF8 - -#define STM32_TIM1_BRK_TIM9_NUMBER 24 -#define STM32_TIM1_UP_TIM10_NUMBER 25 -#define STM32_TIM1_TRGCO_TIM11_NUMBER 26 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_BRK_TIM12_NUMBER 43 -#define STM32_TIM8_UP_TIM13_NUMBER 44 -#define STM32_TIM8_TRGCO_TIM14_NUMBER 45 -#define STM32_TIM8_CC_NUMBER 46 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_USART6_HANDLER Vector15C -#define STM32_UART7_HANDLER Vector188 -#define STM32_UART8_HANDLER Vector18C - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_USART6_NUMBER 71 -#define STM32_UART7_NUMBER 82 -#define STM32_UART8_NUMBER 83 - -/* - * USB/OTG units. - */ -#define STM32_OTG1_HANDLER Vector14C -#define STM32_OTG2_HANDLER Vector174 -#define STM32_OTG2_EP1OUT_HANDLER Vector168 -#define STM32_OTG2_EP1IN_HANDLER Vector16C - -#define STM32_OTG1_NUMBER 67 -#define STM32_OTG2_NUMBER 77 -#define STM32_OTG2_EP1OUT_NUMBER 74 -#define STM32_OTG2_EP1IN_NUMBER 75 - -/* - * FSMC units. - */ -#define STM32_FSMC_HANDLER Vector100 - -#define STM32_FSMC_NUMBER 48 - -/* - * LTDC units. - */ -#define STM32_LTDC_EV_HANDLER Vector1A0 -#define STM32_LTDC_ER_HANDLER Vector1A4 - -#define STM32_LTDC_EV_NUMBER 88 -#define STM32_LTDC_ER_NUMBER 89 - -/* - * DMA2D units. - */ -#define STM32_DMA2D_HANDLER Vector1A8 - -#define STM32_DMA2D_NUMBER 90 - -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/stm32_isr.h + * @brief STM32F7xx ISR handler header. + * + * @addtogroup STM32F7xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM8_SUPPRESS_ISR +#define STM32_TIM9_SUPPRESS_ISR +#define STM32_TIM10_SUPPRESS_ISR +#define STM32_TIM11_SUPPRESS_ISR +#define STM32_TIM12_SUPPRESS_ISR +#define STM32_TIM13_SUPPRESS_ISR +#define STM32_TIM14_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_USART6_SUPPRESS_ISR +#define STM32_UART7_SUPPRESS_ISR +#define STM32_UART8_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC units. + */ +#define STM32_ADC_HANDLER Vector88 + +#define STM32_ADC_NUMBER 18 + +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 +#define STM32_CAN2_TX_HANDLER Vector13C +#define STM32_CAN2_RX0_HANDLER Vector140 +#define STM32_CAN2_RX1_HANDLER Vector144 +#define STM32_CAN2_SCE_HANDLER Vector148 +#define STM32_CAN3_TX_HANDLER Vector1E0 +#define STM32_CAN3_RX0_HANDLER Vector1E4 +#define STM32_CAN3_RX1_HANDLER Vector1E8 +#define STM32_CAN3_SCE_HANDLER Vector1EC + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 +#define STM32_CAN2_TX_NUMBER 63 +#define STM32_CAN2_RX0_NUMBER 64 +#define STM32_CAN2_RX1_NUMBER 65 +#define STM32_CAN2_SCE_NUMBER 66 +#define STM32_CAN3_TX_NUMBER 104 +#define STM32_CAN3_RX0_NUMBER 105 +#define STM32_CAN3_RX1_NUMBER 106 +#define STM32_CAN3_SCE_NUMBER 107 + +/* + * DMA units. + */ +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 + +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* + * EXTI unit. + */ +#define STM32_EXTI0_HANDLER Vector58 +#define STM32_EXTI1_HANDLER Vector5C +#define STM32_EXTI2_HANDLER Vector60 +#define STM32_EXTI3_HANDLER Vector64 +#define STM32_EXTI4_HANDLER Vector68 +#define STM32_EXTI5_9_HANDLER Vector9C +#define STM32_EXTI10_15_HANDLER VectorE0 +#define STM32_EXTI16_HANDLER Vector44 /* PVD */ +#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */ +#define STM32_EXTI18_HANDLER VectorE8 /* USB FS WAKEUP */ +#define STM32_EXTI19_HANDLER Vector138 /* ETH WAKEUP */ +#define STM32_EXTI20_HANDLER Vector170 /* USB HS WAKEUP */ +#define STM32_EXTI21_HANDLER Vector48 /* RTC TAMPER */ +#define STM32_EXTI22_HANDLER Vector4C /* RTC WAKEUP */ +#define STM32_EXTI23_HANDLER Vector1B4 /* LPTIM1 */ + +#define STM32_EXTI0_NUMBER 6 +#define STM32_EXTI1_NUMBER 7 +#define STM32_EXTI2_NUMBER 8 +#define STM32_EXTI3_NUMBER 9 +#define STM32_EXTI4_NUMBER 10 +#define STM32_EXTI5_9_NUMBER 23 +#define STM32_EXTI10_15_NUMBER 40 +#define STM32_EXTI16_NUMBER 1 +#define STM32_EXTI17_NUMBER 41 +#define STM32_EXTI18_NUMBER 42 +#define STM32_EXTI19_NUMBER 62 +#define STM32_EXTI20_NUMBER 76 +#define STM32_EXTI21_NUMBER 2 +#define STM32_EXTI22_NUMBER 3 +#define STM32_EXTI23_NUMBER 93 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C3_EVENT_HANDLER Vector160 +#define STM32_I2C3_ERROR_HANDLER Vector164 +#define STM32_I2C4_EVENT_HANDLER Vector1BC +#define STM32_I2C4_ERROR_HANDLER Vector1C0 + +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 +#define STM32_I2C3_EVENT_NUMBER 72 +#define STM32_I2C3_ERROR_NUMBER 73 +#define STM32_I2C4_EVENT_NUMBER 95 +#define STM32_I2C4_ERROR_NUMBER 96 + +/* + * ETH units. + */ +#define STM32_ETH_HANDLER Vector134 + +#define STM32_ETH_NUMBER 61 + +/* + * QUADSPI units. + */ +#define STM32_QUADSPI1_HANDLER Vector1B0 + +#define STM32_QUADSPI1_NUMBER 92 + +/* + * SDMMC units. + */ +#define STM32_SDMMC1_HANDLER Vector104 +#define STM32_SDMMC2_HANDLER Vector1DC + +#define STM32_SDMMC1_NUMBER 49 +#define STM32_SDMMC2_NUMBER 103 + +/* + * TIM units. + */ +#define STM32_TIM1_BRK_TIM9_HANDLER VectorA0 +#define STM32_TIM1_UP_TIM10_HANDLER VectorA4 +#define STM32_TIM1_TRGCO_TIM11_HANDLER VectorA8 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_BRK_TIM12_HANDLER VectorEC +#define STM32_TIM8_UP_TIM13_HANDLER VectorF0 +#define STM32_TIM8_TRGCO_TIM14_HANDLER VectorF4 +#define STM32_TIM8_CC_HANDLER VectorF8 + +#define STM32_TIM1_BRK_TIM9_NUMBER 24 +#define STM32_TIM1_UP_TIM10_NUMBER 25 +#define STM32_TIM1_TRGCO_TIM11_NUMBER 26 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_BRK_TIM12_NUMBER 43 +#define STM32_TIM8_UP_TIM13_NUMBER 44 +#define STM32_TIM8_TRGCO_TIM14_NUMBER 45 +#define STM32_TIM8_CC_NUMBER 46 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_USART6_HANDLER Vector15C +#define STM32_UART7_HANDLER Vector188 +#define STM32_UART8_HANDLER Vector18C + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_USART6_NUMBER 71 +#define STM32_UART7_NUMBER 82 +#define STM32_UART8_NUMBER 83 + +/* + * USB/OTG units. + */ +#define STM32_OTG1_HANDLER Vector14C +#define STM32_OTG2_HANDLER Vector174 +#define STM32_OTG2_EP1OUT_HANDLER Vector168 +#define STM32_OTG2_EP1IN_HANDLER Vector16C + +#define STM32_OTG1_NUMBER 67 +#define STM32_OTG2_NUMBER 77 +#define STM32_OTG2_EP1OUT_NUMBER 74 +#define STM32_OTG2_EP1IN_NUMBER 75 + +/* + * FSMC units. + */ +#define STM32_FSMC_HANDLER Vector100 + +#define STM32_FSMC_NUMBER 48 + +/* + * LTDC units. + */ +#define STM32_LTDC_EV_HANDLER Vector1A0 +#define STM32_LTDC_ER_HANDLER Vector1A4 + +#define STM32_LTDC_EV_NUMBER 88 +#define STM32_LTDC_ER_NUMBER 89 + +/* + * DMA2D units. + */ +#define STM32_DMA2D_HANDLER Vector1A8 + +#define STM32_DMA2D_NUMBER 90 + +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F7xx/stm32_rcc.h b/os/hal/ports/STM32/STM32F7xx/stm32_rcc.h index a303e04f42..daa5162a2c 100644 --- a/os/hal/ports/STM32/STM32F7xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32F7xx/stm32_rcc.h @@ -1,1700 +1,1700 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f7xx.h. - * - * @addtogroup STM32F7xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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); \ - else \ - RCC->APB1LPENR &= ~(mask); \ - (void)RCC->APB1LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - RCC->APB1LPENR &= ~(mask); \ - (void)RCC->APB1LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @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); \ - else \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB1LPENR &= ~(mask); \ - (void)RCC->AHB1LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1LPENR &= ~(mask); \ - (void)RCC->AHB1LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB2LPENR &= ~(mask); \ - (void)RCC->AHB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2LPENR &= ~(mask); \ - (void)RCC->AHB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB3LPENR &= ~(mask); \ - (void)RCC->AHB3LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3LPENR &= ~(mask); \ - (void)RCC->AHB3LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableADC2() rccDisableAPB2(RCC_APB2ENR_ADC2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableADC3() rccDisableAPB2(RCC_APB2ENR_ADC3EN) - -/** - * @brief Resets the ADC3 peripheral. - * - * @api - */ -#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name BKPSRAM specific RCC operations - * @{ - */ -/** - * @brief Enables the BKPSRAM peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableBKPSRAM(lp) rccEnableAHB1(RCC_AHB1ENR_BKPSRAMEN, lp) - -/** - * @brief Disables the BKPSRAM peripheral clock. - * - * @api - */ -#define rccDisableBKPSRAM() rccDisableAHB1(RCC_AHB1ENR_BKPSRAMEN) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CAN1EN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) - -/** - * @brief Enables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) - -/** - * @brief Disables the CAN2 peripheral clock. - * - * @api - */ -#define rccDisableCAN2() rccDisableAPB1(RCC_APB1ENR_CAN2EN) - -/** - * @brief Resets the CAN2 peripheral. - * - * @api - */ -#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) - -/** - * @brief Resets the CAN3 peripheral. - * - * @api - */ -#define rccResetCAN3() rccResetAPB1(RCC_APB1RSTR_CAN3RST) - -/** - * @brief Enables the CAN3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN3(lp) rccEnableAPB1(RCC_APB1ENR_CAN3EN, lp) - -/** - * @brief Disables the CAN3 peripheral clock. - * - * @api - */ -#define rccDisableCAN3() rccDisableAPB1(RCC_APB1ENR_CAN3EN) -/** @} */ - -/** - * @name ETH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the ETH peripheral clock. - * - * @api - */ -#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \ - RCC_AHB1ENR_ETHMACTXEN | \ - RCC_AHB1ENR_ETHMACRXEN, lp) - -/** - * @brief Disables the ETH peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \ - RCC_AHB1ENR_ETHMACTXEN | \ - RCC_AHB1ENR_ETHMACRXEN) - -/** - * @brief Resets the ETH peripheral. - * - * @api - */ -#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1(RCC_APB1ENR_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C4(lp) rccEnableAPB1(RCC_APB1ENR_I2C4EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @api - */ -#define rccDisableI2C4() rccDisableAPB1(RCC_APB1ENR_I2C4EN) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB1(RCC_APB1RSTR_I2C4RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) - -/** - * @brief Disables the OTG_FS peripheral clock. - * - * @api - */ -#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) - -/** - * @brief Resets the OTG_FS peripheral. - * - * @api - */ -#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) - -/** - * @brief Enables the OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp) - -/** - * @brief Disables the OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableOTG_HS() rccDisableAHB1(RCC_AHB1ENR_OTGHSEN) - -/** - * @brief Resets the OTG_HS peripheral. - * - * @api - */ -#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHRST) - -/** - * @brief Enables the OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSULPIEN, lp) - -/** - * @brief Disables the OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableOTG_HSULPI() rccDisableAHB1(RCC_AHB1ENR_OTGHSULPIEN) -/** @} */ - -/** - * @name QUADSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the QUADSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) - -/** - * @brief Disables the QUADSPI1 peripheral clock. - * - * @api - */ -#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) - -/** - * @brief Resets the QUADSPI1 peripheral. - * - * @api - */ -#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) -/** @} */ - -/** - * @name SDMMC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDMMC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp) - -/** - * @brief Disables the SDMMC1 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN) - -/** - * @brief Resets the SDMMC1 peripheral. - * - * @api - */ -#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST) - -/** - * @brief Enables the SDMMC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC2(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC2EN, lp) - -/** - * @brief Disables the SDMMC2 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC2() rccDisableAPB2(RCC_APB2ENR_SDMMC2EN) - -/** - * @brief Resets the SDMMC2 peripheral. - * - * @api - */ -#define rccResetSDMMC2() rccResetAPB2(RCC_APB2RSTR_SDMMC2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) - -/** - * @brief Enables the SPI4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) - -/** - * @brief Disables the SPI4 peripheral clock. - * - * @api - */ -#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) - -/** - * @brief Resets the SPI4 peripheral. - * - * @api - */ -#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) - -/** - * @brief Enables the SPI5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp) - -/** - * @brief Disables the SPI5 peripheral clock. - * - * @api - */ -#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN) - -/** - * @brief Resets the SPI5 peripheral. - * - * @api - */ -#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST) - -/** - * @brief Enables the SPI6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI6(lp) rccEnableAPB2(RCC_APB2ENR_SPI6EN, lp) - -/** - * @brief Disables the SPI6 peripheral clock. - * - * @api - */ -#define rccDisableSPI6() rccDisableAPB2(RCC_APB2ENR_SPI6EN) - -/** - * @brief Resets the SPI6 peripheral. - * - * @api - */ -#define rccResetSPI6() rccResetAPB2(RCC_APB2RSTR_SPI6RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM9 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) - -/** - * @brief Disables the TIM9 peripheral clock. - * - * @api - */ -#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) - -/** - * @brief Resets the TIM9 peripheral. - * - * @api - */ -#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) - -/** - * @brief Enables the TIM10 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) - -/** - * @brief Disables the TIM10 peripheral clock. - * - * @api - */ -#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) - -/** - * @brief Resets the TIM10 peripheral. - * - * @api - */ -#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) - -/** - * @brief Enables the TIM11 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) - -/** - * @brief Disables the TIM11 peripheral clock. - * - * @api - */ -#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) - -/** - * @brief Resets the TIM11 peripheral. - * - * @api - */ -#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) - -/** - * @brief Enables the TIM12 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) - -/** - * @brief Disables the TIM12 peripheral clock. - * - * @api - */ -#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) - -/** - * @brief Resets the TIM12 peripheral. - * - * @api - */ -#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) - -/** - * @brief Enables the TIM13 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) - -/** - * @brief Disables the TIM13 peripheral clock. - * - * @api - */ -#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) - -/** - * @brief Resets the TIM13 peripheral. - * - * @api - */ -#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) - -/** - * @brief Resets the USART6 peripheral. - * - * @api - */ -#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) - -/** - * @brief Enables the UART7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART7(lp) rccEnableAPB1(RCC_APB1ENR_UART7EN, lp) - -/** - * @brief Disables the UART7 peripheral clock. - * - * @api - */ -#define rccDisableUART7() rccDisableAPB1(RCC_APB1ENR_UART7EN) - -/** - * @brief Resets the UART7 peripheral. - * - * @api - */ -#define rccResetUART7() rccResetAPB1(RCC_APB1RSTR_UART7RST) - -/** - * @brief Enables the UART8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART8(lp) rccEnableAPB1(RCC_APB1ENR_UART8EN, lp) - -/** - * @brief Disables the UART8 peripheral clock. - * - * @api - */ -#define rccDisableUART8() rccDisableAPB1(RCC_APB1ENR_UART8EN) - -/** - * @brief Resets the UART8 peripheral. - * - * @api - */ -#define rccResetUART8() rccResetAPB1(RCC_APB1RSTR_UART8RST) -/** @} */ - -/** - * @name LTDC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the LTDC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLTDC(lp) rccEnableAPB2(RCC_APB2ENR_LTDCEN, lp) - -/** - * @brief Disables the LTDC peripheral clock. - * - * @api - */ -#define rccDisableLTDC() rccDisableAPB2(RCC_APB2ENR_LTDCEN) - -/** - * @brief Resets the LTDC peripheral. - * - * @api - */ -#define rccResetLTDC() rccResetAPB2(RCC_APB2RSTR_LTDCRST) -/** @} */ - -/** - * @name DMA2D peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA2D peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2D(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2DEN, lp) - -/** - * @brief Disables the DMA2D peripheral clock. - * - * @api - */ -#define rccDisableDMA2D() rccDisableAHB1(RCC_AHB1ENR_DMA2DEN) - -/** - * @brief Resets the DMA2D peripheral. - * - * @api - */ -#define rccResetDMA2D() rccResetAHB1(RCC_AHB1RSTR_DMA2DRST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) -/** @} */ - -/** - * @name HASH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRYP peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRYP(lp) rccEnableAHB2(RCC_AHB2ENR_CRYPEN, lp) - -/** - * @brief Disables the CRYP peripheral clock. - * - * @api - */ -#define rccDisableCRYP() rccDisableAHB2(RCC_AHB2ENR_CRYPEN) - -/** - * @brief Resets the CRYP peripheral. - * - * @api - */ -#define rccResetCRYP() rccResetAHB2(RCC_AHB2RSTR_CRYPRST) -/** @} */ - -/** - * @name HASH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the HASH peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableHASH(lp) rccEnableAHB2(RCC_AHB2ENR_HASHEN, lp) - -/** - * @brief Disables the HASH peripheral clock. - * - * @api - */ -#define rccDisableHASH() rccDisableAHB2(RCC_AHB2ENR_HASHEN) - -/** - * @brief Resets the HASH peripheral. - * - * @api - */ -#define rccResetHASH() rccResetAHB2(RCC_AHB2RSTR_HASHRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#if defined(STM32_FSMC_IS_FMC) - #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) -#else - #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp) -#endif - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#if defined(STM32_FSMC_IS_FMC) - #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) -#else - #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN) -#endif - -/** - * @brief Resets the FSMC peripheral. - * - * @api - */ -#if defined(STM32_FSMC_IS_FMC) - #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) -#else - #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST) -#endif -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f7xx.h. + * + * @addtogroup STM32F7xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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); \ + else \ + RCC->APB1LPENR &= ~(mask); \ + (void)RCC->APB1LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + RCC->APB1LPENR &= ~(mask); \ + (void)RCC->APB1LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @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); \ + else \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB1LPENR &= ~(mask); \ + (void)RCC->AHB1LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1LPENR &= ~(mask); \ + (void)RCC->AHB1LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB2LPENR &= ~(mask); \ + (void)RCC->AHB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2LPENR &= ~(mask); \ + (void)RCC->AHB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB3LPENR &= ~(mask); \ + (void)RCC->AHB3LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3LPENR &= ~(mask); \ + (void)RCC->AHB3LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableADC2() rccDisableAPB2(RCC_APB2ENR_ADC2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableADC3() rccDisableAPB2(RCC_APB2ENR_ADC3EN) + +/** + * @brief Resets the ADC3 peripheral. + * + * @api + */ +#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name BKPSRAM specific RCC operations + * @{ + */ +/** + * @brief Enables the BKPSRAM peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableBKPSRAM(lp) rccEnableAHB1(RCC_AHB1ENR_BKPSRAMEN, lp) + +/** + * @brief Disables the BKPSRAM peripheral clock. + * + * @api + */ +#define rccDisableBKPSRAM() rccDisableAHB1(RCC_AHB1ENR_BKPSRAMEN) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1(RCC_APB1ENR_CAN1EN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) + +/** + * @brief Enables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) + +/** + * @brief Disables the CAN2 peripheral clock. + * + * @api + */ +#define rccDisableCAN2() rccDisableAPB1(RCC_APB1ENR_CAN2EN) + +/** + * @brief Resets the CAN2 peripheral. + * + * @api + */ +#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) + +/** + * @brief Resets the CAN3 peripheral. + * + * @api + */ +#define rccResetCAN3() rccResetAPB1(RCC_APB1RSTR_CAN3RST) + +/** + * @brief Enables the CAN3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN3(lp) rccEnableAPB1(RCC_APB1ENR_CAN3EN, lp) + +/** + * @brief Disables the CAN3 peripheral clock. + * + * @api + */ +#define rccDisableCAN3() rccDisableAPB1(RCC_APB1ENR_CAN3EN) +/** @} */ + +/** + * @name ETH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the ETH peripheral clock. + * + * @api + */ +#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \ + RCC_AHB1ENR_ETHMACTXEN | \ + RCC_AHB1ENR_ETHMACRXEN, lp) + +/** + * @brief Disables the ETH peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \ + RCC_AHB1ENR_ETHMACTXEN | \ + RCC_AHB1ENR_ETHMACRXEN) + +/** + * @brief Resets the ETH peripheral. + * + * @api + */ +#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1(RCC_APB1ENR_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C4(lp) rccEnableAPB1(RCC_APB1ENR_I2C4EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @api + */ +#define rccDisableI2C4() rccDisableAPB1(RCC_APB1ENR_I2C4EN) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB1(RCC_APB1RSTR_I2C4RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) + +/** + * @brief Disables the OTG_FS peripheral clock. + * + * @api + */ +#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) + +/** + * @brief Resets the OTG_FS peripheral. + * + * @api + */ +#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) + +/** + * @brief Enables the OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp) + +/** + * @brief Disables the OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableOTG_HS() rccDisableAHB1(RCC_AHB1ENR_OTGHSEN) + +/** + * @brief Resets the OTG_HS peripheral. + * + * @api + */ +#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHRST) + +/** + * @brief Enables the OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSULPIEN, lp) + +/** + * @brief Disables the OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableOTG_HSULPI() rccDisableAHB1(RCC_AHB1ENR_OTGHSULPIEN) +/** @} */ + +/** + * @name QUADSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the QUADSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) + +/** + * @brief Disables the QUADSPI1 peripheral clock. + * + * @api + */ +#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) + +/** + * @brief Resets the QUADSPI1 peripheral. + * + * @api + */ +#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) +/** @} */ + +/** + * @name SDMMC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDMMC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp) + +/** + * @brief Disables the SDMMC1 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN) + +/** + * @brief Resets the SDMMC1 peripheral. + * + * @api + */ +#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST) + +/** + * @brief Enables the SDMMC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC2(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC2EN, lp) + +/** + * @brief Disables the SDMMC2 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC2() rccDisableAPB2(RCC_APB2ENR_SDMMC2EN) + +/** + * @brief Resets the SDMMC2 peripheral. + * + * @api + */ +#define rccResetSDMMC2() rccResetAPB2(RCC_APB2RSTR_SDMMC2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1(RCC_APB1ENR_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) + +/** + * @brief Enables the SPI4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) + +/** + * @brief Disables the SPI4 peripheral clock. + * + * @api + */ +#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) + +/** + * @brief Resets the SPI4 peripheral. + * + * @api + */ +#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) + +/** + * @brief Enables the SPI5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp) + +/** + * @brief Disables the SPI5 peripheral clock. + * + * @api + */ +#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN) + +/** + * @brief Resets the SPI5 peripheral. + * + * @api + */ +#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST) + +/** + * @brief Enables the SPI6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI6(lp) rccEnableAPB2(RCC_APB2ENR_SPI6EN, lp) + +/** + * @brief Disables the SPI6 peripheral clock. + * + * @api + */ +#define rccDisableSPI6() rccDisableAPB2(RCC_APB2ENR_SPI6EN) + +/** + * @brief Resets the SPI6 peripheral. + * + * @api + */ +#define rccResetSPI6() rccResetAPB2(RCC_APB2RSTR_SPI6RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM9 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) + +/** + * @brief Disables the TIM9 peripheral clock. + * + * @api + */ +#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) + +/** + * @brief Resets the TIM9 peripheral. + * + * @api + */ +#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) + +/** + * @brief Enables the TIM10 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) + +/** + * @brief Disables the TIM10 peripheral clock. + * + * @api + */ +#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) + +/** + * @brief Resets the TIM10 peripheral. + * + * @api + */ +#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) + +/** + * @brief Enables the TIM11 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) + +/** + * @brief Disables the TIM11 peripheral clock. + * + * @api + */ +#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) + +/** + * @brief Resets the TIM11 peripheral. + * + * @api + */ +#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) + +/** + * @brief Enables the TIM12 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) + +/** + * @brief Disables the TIM12 peripheral clock. + * + * @api + */ +#define rccDisableTIM12() rccDisableAPB1(RCC_APB1ENR_TIM12EN) + +/** + * @brief Resets the TIM12 peripheral. + * + * @api + */ +#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) + +/** + * @brief Enables the TIM13 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM13(lp) rccEnableAPB1(RCC_APB1ENR_TIM13EN, lp) + +/** + * @brief Disables the TIM13 peripheral clock. + * + * @api + */ +#define rccDisableTIM13() rccDisableAPB1(RCC_APB1ENR_TIM13EN) + +/** + * @brief Resets the TIM13 peripheral. + * + * @api + */ +#define rccResetTIM13() rccResetAPB1(RCC_APB1RSTR_TIM13RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPB1(RCC_APB1ENR_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) + +/** + * @brief Resets the USART6 peripheral. + * + * @api + */ +#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) + +/** + * @brief Enables the UART7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART7(lp) rccEnableAPB1(RCC_APB1ENR_UART7EN, lp) + +/** + * @brief Disables the UART7 peripheral clock. + * + * @api + */ +#define rccDisableUART7() rccDisableAPB1(RCC_APB1ENR_UART7EN) + +/** + * @brief Resets the UART7 peripheral. + * + * @api + */ +#define rccResetUART7() rccResetAPB1(RCC_APB1RSTR_UART7RST) + +/** + * @brief Enables the UART8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART8(lp) rccEnableAPB1(RCC_APB1ENR_UART8EN, lp) + +/** + * @brief Disables the UART8 peripheral clock. + * + * @api + */ +#define rccDisableUART8() rccDisableAPB1(RCC_APB1ENR_UART8EN) + +/** + * @brief Resets the UART8 peripheral. + * + * @api + */ +#define rccResetUART8() rccResetAPB1(RCC_APB1RSTR_UART8RST) +/** @} */ + +/** + * @name LTDC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the LTDC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLTDC(lp) rccEnableAPB2(RCC_APB2ENR_LTDCEN, lp) + +/** + * @brief Disables the LTDC peripheral clock. + * + * @api + */ +#define rccDisableLTDC() rccDisableAPB2(RCC_APB2ENR_LTDCEN) + +/** + * @brief Resets the LTDC peripheral. + * + * @api + */ +#define rccResetLTDC() rccResetAPB2(RCC_APB2RSTR_LTDCRST) +/** @} */ + +/** + * @name DMA2D peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA2D peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2D(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2DEN, lp) + +/** + * @brief Disables the DMA2D peripheral clock. + * + * @api + */ +#define rccDisableDMA2D() rccDisableAHB1(RCC_AHB1ENR_DMA2DEN) + +/** + * @brief Resets the DMA2D peripheral. + * + * @api + */ +#define rccResetDMA2D() rccResetAHB1(RCC_AHB1RSTR_DMA2DRST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) +/** @} */ + +/** + * @name HASH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRYP peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRYP(lp) rccEnableAHB2(RCC_AHB2ENR_CRYPEN, lp) + +/** + * @brief Disables the CRYP peripheral clock. + * + * @api + */ +#define rccDisableCRYP() rccDisableAHB2(RCC_AHB2ENR_CRYPEN) + +/** + * @brief Resets the CRYP peripheral. + * + * @api + */ +#define rccResetCRYP() rccResetAHB2(RCC_AHB2RSTR_CRYPRST) +/** @} */ + +/** + * @name HASH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the HASH peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableHASH(lp) rccEnableAHB2(RCC_AHB2ENR_HASHEN, lp) + +/** + * @brief Disables the HASH peripheral clock. + * + * @api + */ +#define rccDisableHASH() rccDisableAHB2(RCC_AHB2ENR_HASHEN) + +/** + * @brief Resets the HASH peripheral. + * + * @api + */ +#define rccResetHASH() rccResetAHB2(RCC_AHB2RSTR_HASHRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#if defined(STM32_FSMC_IS_FMC) + #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) +#else + #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp) +#endif + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#if defined(STM32_FSMC_IS_FMC) + #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) +#else + #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN) +#endif + +/** + * @brief Resets the FSMC peripheral. + * + * @api + */ +#if defined(STM32_FSMC_IS_FMC) + #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) +#else + #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST) +#endif +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32F7xx/stm32_registry.h b/os/hal/ports/STM32/STM32F7xx/stm32_registry.h index e67e7372fb..0928be4e22 100644 --- a/os/hal/ports/STM32/STM32F7xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32F7xx/stm32_registry.h @@ -1,1107 +1,1107 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/stm32_registry.h - * @brief STM32F7xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F7xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 128 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 21 -#define STM32_RTC_WKUP_EXTI 22 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI21_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI22_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ -} while (false) - -#if defined(STM32F732xx) || defined(STM32F733xx) || defined(STM32F756xx) || \ - defined(STM32F777xx) || defined(STM32F779xx) || defined(__DOXYGEN__) -#define STM32_HAS_HASH1 TRUE -#define STM32_HAS_CRYP1 TRUE -#define STM32_HASH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_HASH1_DMA_CHN 0x20000000 -#define STM32_CRYP1_IN_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 6) -#define STM32_CRYP1_IN_DMA_CHN 0x02000000 -#define STM32_CRYP1_OUT_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) -#define STM32_CRYP1_OUT_DMA_CHN 0x00200000 - -#else /* Devices without cryp nor hash.*/ -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE -#endif - -/*===========================================================================*/ -/* STM32F722xx, STM32F723xx, STM32F732xx, STM32F733xx. */ -/*===========================================================================*/ -#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || \ - defined(STM32F733xx) || defined(__DOXYGEN__) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 28 - -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 24 -#define STM32_EXTI_IMR1_MASK 0xFF000000 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_RX_DMA_CHN 0x00000310 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_QUADSPI1_DMA_CHN 0x30000000 - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_HAS_INTERRUPTS FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x04004000 - -#define STM32_HAS_SDMMC2 TRUE -#define STM32_SDC_SDMMC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SDC_SDMMC2_DMA_CHN 0x00B0000B - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_UART7_RX_DMA_CHN 0x00005000 -#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_UART7_TX_DMA_CHN 0x00000050 - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART8_RX_DMA_CHN 0x05000000 -#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART8_TX_DMA_CHN 0x00000005 - -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 8 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32F722xx) || defined(STM32F723xx) || - defined(STM32F732xx) || defined(STM32F733xx) */ - -/*===========================================================================*/ -/* STM32F745xx, STM32F746xx, STM32F756xx. */ -/*===========================================================================*/ -#if defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F756xx) || \ - defined(__DOXYGEN__) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 28 -#define STM32_CAN3_MAX_FILTERS 14 - -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 TRUE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 24 -#define STM32_EXTI_IMR1_MASK 0xFF000000 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ TRUE -#define STM32_HAS_GPIOK TRUE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN | \ - RCC_AHB1ENR_GPIOJEN | \ - RCC_AHB1ENR_GPIOKEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_RX_DMA_CHN 0x00000310 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C4_RX_DMA_CHN 0x00000200 -#define STM32_I2C4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C4_TX_DMA_CHN 0x00200000 - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_QUADSPI1_DMA_CHN 0x30000000 - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_HAS_INTERRUPTS FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x04004000 - -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050040 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00702000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI6 TRUE -#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI6_RX_DMA_CHN 0x01000000 -#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI6_TX_DMA_CHN 0x00100000 - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_UART7_RX_DMA_CHN 0x00005000 -#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_UART7_TX_DMA_CHN 0x00000050 - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART8_RX_DMA_CHN 0x05000000 -#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART8_TX_DMA_CHN 0x00000005 - -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 8 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F756xx) */ - -/*===========================================================================*/ -/* STM32F765xx, STM32F767xx, STM32F769xx, STM32F777xx, STM32F779xx. */ -/*===========================================================================*/ -#if defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || \ - defined(STM32F777xx) || defined(STM32F779xx) || \ - defined(__DOXYGEN__) -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 28 -#define STM32_CAN3_MAX_FILTERS 14 - -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 TRUE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_DAC1_CH1_DMA_CHN 0x00700000 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_DAC1_CH2_DMA_CHN 0x07000000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_CACHE_HANDLING TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE - -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 24 -#define STM32_EXTI_IMR1_MASK 0xFF000000 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ TRUE -#define STM32_HAS_GPIOK TRUE -#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ - RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | \ - RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | \ - RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | \ - RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN | \ - RCC_AHB1ENR_GPIOJEN | \ - RCC_AHB1ENR_GPIOKEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C2_TX_DMA_CHN 0x70080000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_RX_DMA_CHN 0x00000310 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_I2C3_TX_DMA_CHN 0x00030008 - -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 1)) -#define STM32_I2C4_RX_DMA_CHN 0x00000280 -#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C4_TX_DMA_CHN 0x08200000 - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_QUADSPI1_DMA_CHN 0x30000B00 - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_HAS_INTERRUPTS FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x04004000 - -#define STM32_HAS_SDMMC2 TRUE -#define STM32_SDC_SDMMC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SDC_SDMMC2_DMA_CHN 0x00B0000B - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI2_RX_DMA_CHN 0x00000090 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_TX_DMA_CHN 0x09000000 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX 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 - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI4_RX_DMA_CHN 0x00005004 -#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI4_TX_DMA_CHN 0x00050940 - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3)|\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI5_RX_DMA_CHN 0x00902000 -#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4)|\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI5_TX_DMA_CHN 0x07020000 - -#define STM32_HAS_SPI6 TRUE -#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SPI6_RX_DMA_CHN 0x01000000 -#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI6_TX_DMA_CHN 0x00100000 - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 1 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 1 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -#define STM32_HAS_UART7 TRUE -#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_UART7_RX_DMA_CHN 0x00005000 -#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_UART7_TX_DMA_CHN 0x00000050 - -#define STM32_HAS_UART8 TRUE -#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_UART8_RX_DMA_CHN 0x05000000 -#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART8_TX_DMA_CHN 0x00000005 - -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 8 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || - defined(STM32F777xx) || defined(STM32F779xx) */ -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/stm32_registry.h + * @brief STM32F7xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F7xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 21 +#define STM32_RTC_WKUP_EXTI 22 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI21_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI22_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ +} while (false) + +#if defined(STM32F732xx) || defined(STM32F733xx) || defined(STM32F756xx) || \ + defined(STM32F777xx) || defined(STM32F779xx) || defined(__DOXYGEN__) +#define STM32_HAS_HASH1 TRUE +#define STM32_HAS_CRYP1 TRUE +#define STM32_HASH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_HASH1_DMA_CHN 0x20000000 +#define STM32_CRYP1_IN_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 6) +#define STM32_CRYP1_IN_DMA_CHN 0x02000000 +#define STM32_CRYP1_OUT_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) +#define STM32_CRYP1_OUT_DMA_CHN 0x00200000 + +#else /* Devices without cryp nor hash.*/ +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE +#endif + +/*===========================================================================*/ +/* STM32F722xx, STM32F723xx, STM32F732xx, STM32F733xx. */ +/*===========================================================================*/ +#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || \ + defined(STM32F733xx) || defined(__DOXYGEN__) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 28 + +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 24 +#define STM32_EXTI_IMR1_MASK 0xFF000000 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_RX_DMA_CHN 0x00000310 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_QUADSPI1_DMA_CHN 0x30000000 + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_HAS_INTERRUPTS FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x04004000 + +#define STM32_HAS_SDMMC2 TRUE +#define STM32_SDC_SDMMC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SDC_SDMMC2_DMA_CHN 0x00B0000B + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_UART7_RX_DMA_CHN 0x00005000 +#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_UART7_TX_DMA_CHN 0x00000050 + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART8_RX_DMA_CHN 0x05000000 +#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART8_TX_DMA_CHN 0x00000005 + +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 8 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32F722xx) || defined(STM32F723xx) || + defined(STM32F732xx) || defined(STM32F733xx) */ + +/*===========================================================================*/ +/* STM32F745xx, STM32F746xx, STM32F756xx. */ +/*===========================================================================*/ +#if defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F756xx) || \ + defined(__DOXYGEN__) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 28 +#define STM32_CAN3_MAX_FILTERS 14 + +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 TRUE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 24 +#define STM32_EXTI_IMR1_MASK 0xFF000000 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ TRUE +#define STM32_HAS_GPIOK TRUE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN | \ + RCC_AHB1ENR_GPIOJEN | \ + RCC_AHB1ENR_GPIOKEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_RX_DMA_CHN 0x00000310 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C4_RX_DMA_CHN 0x00000200 +#define STM32_I2C4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C4_TX_DMA_CHN 0x00200000 + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_QUADSPI1_DMA_CHN 0x30000000 + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_HAS_INTERRUPTS FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x04004000 + +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX 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_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050040 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00702000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI6 TRUE +#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI6_RX_DMA_CHN 0x01000000 +#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI6_TX_DMA_CHN 0x00100000 + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_UART7_RX_DMA_CHN 0x00005000 +#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_UART7_TX_DMA_CHN 0x00000050 + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART8_RX_DMA_CHN 0x05000000 +#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART8_TX_DMA_CHN 0x00000005 + +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 8 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F756xx) */ + +/*===========================================================================*/ +/* STM32F765xx, STM32F767xx, STM32F769xx, STM32F777xx, STM32F779xx. */ +/*===========================================================================*/ +#if defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || \ + defined(STM32F777xx) || defined(STM32F779xx) || \ + defined(__DOXYGEN__) +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 28 +#define STM32_CAN3_MAX_FILTERS 14 + +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 TRUE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_DAC1_CH1_DMA_CHN 0x00700000 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_DAC1_CH2_DMA_CHN 0x07000000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_CACHE_HANDLING TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE + +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 24 +#define STM32_EXTI_IMR1_MASK 0xFF000000 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ TRUE +#define STM32_HAS_GPIOK TRUE +#define STM32_GPIO_EN_MASK (RCC_AHB1ENR_GPIOAEN | \ + RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | \ + RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | \ + RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | \ + RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN | \ + RCC_AHB1ENR_GPIOJEN | \ + RCC_AHB1ENR_GPIOKEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C2_TX_DMA_CHN 0x70080000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_RX_DMA_CHN 0x00000310 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_I2C3_TX_DMA_CHN 0x00030008 + +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 1)) +#define STM32_I2C4_RX_DMA_CHN 0x00000280 +#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C4_TX_DMA_CHN 0x08200000 + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_QUADSPI1_DMA_CHN 0x30000B00 + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_HAS_INTERRUPTS FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x04004000 + +#define STM32_HAS_SDMMC2 TRUE +#define STM32_SDC_SDMMC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SDC_SDMMC2_DMA_CHN 0x00B0000B + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI2_RX_DMA_CHN 0x00000090 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_TX_DMA_CHN 0x09000000 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX 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 + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI4_RX_DMA_CHN 0x00005004 +#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI4_TX_DMA_CHN 0x00050940 + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3)|\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI5_RX_DMA_CHN 0x00902000 +#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4)|\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI5_TX_DMA_CHN 0x07020000 + +#define STM32_HAS_SPI6 TRUE +#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SPI6_RX_DMA_CHN 0x01000000 +#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI6_TX_DMA_CHN 0x00100000 + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 1 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 1 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +#define STM32_HAS_UART7 TRUE +#define STM32_UART7_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_UART7_RX_DMA_CHN 0x00005000 +#define STM32_UART7_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_UART7_TX_DMA_CHN 0x00000050 + +#define STM32_HAS_UART8 TRUE +#define STM32_UART8_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_UART8_RX_DMA_CHN 0x05000000 +#define STM32_UART8_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART8_TX_DMA_CHN 0x00000005 + +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 8 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || + defined(STM32F777xx) || defined(STM32F779xx) */ +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.c b/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.c index 20af8885e7..22784ecc8a 100644 --- a/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.c +++ b/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.c @@ -1,608 +1,608 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_efl_lld.c - * @brief STM32G07/8nxx Embedded Flash subsystem low level driver source. - * - * @addtogroup HAL_EFL - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define STM32_FLASH_LINE_SIZE 8U -#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U) - -#define FLASH_PDKEY1 0x04152637U -#define FLASH_PDKEY2 0xFAFBFCFDU - -#define FLASH_KEY1 0x45670123U -#define FLASH_KEY2 0xCDEF89ABU - -#define FLASH_OPTKEY1 0x08192A3BU -#define FLASH_OPTKEY2 0x4C5D6E7FU - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief EFL1 driver identifier. - */ -EFlashDriver EFLD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/* The descriptor for 64K devices. */ -static const flash_descriptor_t efl_lld_size1[STM32_FLASH_NUMBER_OF_BANKS] = { - { /* Bank 1. */ - .attributes = FLASH_ATTR_ERASED_IS_ONE | - FLASH_ATTR_MEMORY_MAPPED | - FLASH_ATTR_ECC_CAPABLE | - FLASH_ATTR_ECC_ZERO_LINE_CAPABLE, - .page_size = STM32_FLASH_LINE_SIZE, - .sectors_count = STM32_FLASH_SECTORS_TOTAL_64K, - .sectors = NULL, - .sectors_size = STM32_FLASH_SECTOR_SIZE_64K, - .address = (uint8_t *)FLASH_BASE, - .size = STM32_FLASH_SIZE_64K * STM32_FLASH_SIZE_SCALE - } -}; - -/* The descriptor for 128K devices. */ -static const flash_descriptor_t efl_lld_size2[STM32_FLASH_NUMBER_OF_BANKS] = { - { /* Bank 1. */ - .attributes = FLASH_ATTR_ERASED_IS_ONE | - FLASH_ATTR_MEMORY_MAPPED | - FLASH_ATTR_ECC_CAPABLE | - FLASH_ATTR_ECC_ZERO_LINE_CAPABLE, - .page_size = STM32_FLASH_LINE_SIZE, - .sectors_count = STM32_FLASH_SECTORS_TOTAL_128K, - .sectors = NULL, - .sectors_size = STM32_FLASH_SECTOR_SIZE_128K, - .address = (uint8_t *)FLASH_BASE, - .size = STM32_FLASH_SIZE_128K * STM32_FLASH_SIZE_SCALE - } -}; - -/* Table describing possible flash sizes and descriptors for this device. */ -static const efl_lld_size_t efl_lld_flash_sizes[] = { - { - .desc = efl_lld_size1 - }, - { - .desc = efl_lld_size2 - } -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static inline void stm32_flash_lock(EFlashDriver *eflp) { - - eflp->flash->CR |= FLASH_CR_LOCK; -} - -static inline void stm32_flash_unlock(EFlashDriver *eflp) { - - eflp->flash->KEYR |= FLASH_KEY1; - eflp->flash->KEYR |= FLASH_KEY2; -} - -static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) { - - eflp->flash->CR |= FLASH_CR_PG; -} - -static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) { - - eflp->flash->CR &= ~FLASH_CR_PG; -} - -static inline void stm32_flash_clear_status(EFlashDriver *eflp) { - - eflp->flash->SR = 0x0000FFFFU; -} - -static inline void stm32_flash_wait_busy(EFlashDriver *eflp) { - - /* Wait for busy bit clear.*/ - while ((eflp->flash->SR & FLASH_SR_BSY1) != 0U) { - } -} - -static inline size_t stm32_flash_get_size(void) { - return *(uint16_t*)((uint32_t) STM32_FLASH_SIZE_REGISTER) * STM32_FLASH_SIZE_SCALE; -} - -static inline bool stm32_flash_dual_bank(EFlashDriver *eflp) { - -#if STM32_FLASH_NUMBER_OF_BANKS > 1 -#error "Device settings incorrectly configured - single bank mode only supported" -#endif - (void)eflp; - return false; -} - -static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) { - uint32_t sr = eflp->flash->SR; - - /* Clearing error conditions.*/ - eflp->flash->SR = sr & 0x0000FFFFU; - - /* Some errors are only caught by assertion.*/ - osalDbgAssert((sr & (FLASH_SR_FASTERR | - FLASH_SR_MISERR | - FLASH_SR_SIZERR)) == 0U, "unexpected flash error"); - - /* Decoding relevant errors.*/ - if ((sr & FLASH_SR_WRPERR) != 0U) { - return FLASH_ERROR_HW_FAILURE; - } - - if ((sr & (FLASH_SR_PGAERR | FLASH_SR_PROGERR | FLASH_SR_OPERR)) != 0U) { - return eflp->state == FLASH_PGM ? FLASH_ERROR_PROGRAM : FLASH_ERROR_ERASE; - } - - return FLASH_NO_ERROR; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level Embedded Flash driver initialization. - * - * @notapi - */ -void efl_lld_init(void) { - - /* Driver initialization.*/ - eflObjectInit(&EFLD1); - EFLD1.flash = FLASH; - /* Find the size of the flash and set descriptor reference. */ - uint8_t i; - for (i = 0; i < (sizeof(efl_lld_flash_sizes) / sizeof(efl_lld_size_t)); i++) { - if (efl_lld_flash_sizes[i].desc->size == stm32_flash_get_size()) { - EFLD1.descriptor = efl_lld_flash_sizes[i].desc; - if (stm32_flash_dual_bank(&EFLD1)) { - /* Point to the dual bank descriptor. */ - EFLD1.descriptor++; - } - return; - } - } - osalDbgAssert(false, "invalid flash configuration"); -} - -/** - * @brief Configures and activates the Embedded Flash peripheral. - * - * @param[in] eflp pointer to a @p EFlashDriver structure - * - * @notapi - */ -void efl_lld_start(EFlashDriver *eflp) { - stm32_flash_unlock(eflp); - FLASH->CR = 0x00000000U; -} - -/** - * @brief Deactivates the Embedded Flash peripheral. - * - * @param[in] eflp pointer to a @p EFlashDriver structure - * - * @notapi - */ -void efl_lld_stop(EFlashDriver *eflp) { - - stm32_flash_lock(eflp); -} - -/** - * @brief Gets the flash descriptor structure. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @return A flash device descriptor. - * @retval Pointer to single bank if DBM not enabled. - * @retval Pointer to bank1 if DBM enabled. - * - * @notapi - */ -const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { - EFlashDriver *devp = (EFlashDriver *)instance; - return devp->descriptor; -} - -/** - * @brief Read operation. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] offset offset within full flash address space - * @param[in] n number of bytes to be read - * @param[out] rp pointer to the data buffer - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_READ if the read operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_read(void *instance, flash_offset_t offset, - size_t n, uint8_t *rp) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err = FLASH_NO_ERROR; - - osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); - - const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); - osalDbgCheck((size_t)offset + n <= (size_t)bank->size); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No reading while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_READ state while the operation is performed.*/ - devp->state = FLASH_READ; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Actual read implementation.*/ - memcpy((void *)rp, (const void *)efl_lld_get_descriptor(instance)->address - + offset, n); - - /* Checking for errors after reading.*/ - if ((devp->flash->SR & FLASH_SR_RDERR) != 0U) { - err = FLASH_ERROR_READ; - } - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; - -} - -/** - * @brief Program operation. - * @note The device supports ECC, it is only possible to write erased - * pages once except when writing all zeroes. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] offset offset within full flash address space - * @param[in] n number of bytes to be programmed - * @param[in] pp pointer to the data buffer - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_PROGRAM if the program operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_program(void *instance, flash_offset_t offset, - size_t n, const uint8_t *pp) { - EFlashDriver *devp = (EFlashDriver *)instance; - const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); - flash_error_t err = FLASH_NO_ERROR; - - osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); - osalDbgCheck((size_t)offset + n <= (size_t)bank->size); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No programming while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_PGM; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Enabling PGM mode in the controller.*/ - stm32_flash_enable_pgm(devp); - - /* Actual program implementation.*/ - while (n > 0U) { - volatile uint32_t *address; - - union { - uint32_t w[STM32_FLASH_LINE_SIZE / sizeof (uint32_t)]; - uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)]; - } line; - - /* Unwritten bytes are initialized to all ones.*/ - line.w[0] = 0xFFFFFFFFU; - line.w[1] = 0xFFFFFFFFU; - - /* Programming address aligned to flash lines.*/ - address = (volatile uint32_t *)(bank->address + - (offset & ~STM32_FLASH_LINE_MASK)); - - /* Copying data inside the prepared line.*/ - do { - line.b[offset & STM32_FLASH_LINE_MASK] = *pp; - offset++; - n--; - pp++; - } - while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U)); - - /* Programming line.*/ - address[0] = line.w[0]; - address[1] = line.w[1]; - stm32_flash_wait_busy(devp); - err = stm32_flash_check_errors(devp); - if (err != FLASH_NO_ERROR) { - break; - } - } - - /* Disabling PGM mode in the controller.*/ - stm32_flash_disable_pgm(devp); - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -/** - * @brief Starts a whole-device erase operation. - * @note This function only erases bank 2 if it is present. Bank 1 is not - * allowed since it is normally where the primary program is located. - * Pages on bank 1 can be individually erased. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_start_erase_all(void *instance) { - EFlashDriver *devp = (EFlashDriver *)instance; - - osalDbgCheck(instance != NULL); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No erasing while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - -#if defined(FLASH_CR_MER2) - /* If dual bank is active then mass erase bank2. */ - if (stm32_flash_dual_bank(devp)) { - - /* FLASH_ERASE state while the operation is performed.*/ - devp->state = FLASH_ERASE; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - devp->flash->CR |= FLASH_CR_MER2; - devp->flash->CR |= FLASH_CR_STRT; - return FLASH_NO_ERROR; - } -#endif - - /* Mass erase not allowed. */ - return FLASH_ERROR_UNIMPLEMENTED; -} - -/** - * @brief Starts an sector erase operation. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] sector sector to be erased - * this is an index within the total sectors - * in a flash bank - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_start_erase_sector(void *instance, - flash_sector_t sector) { - EFlashDriver *devp = (EFlashDriver *)instance; - const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); - osalDbgCheck(instance != NULL); - osalDbgCheck(sector < bank->sectors_count); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No erasing while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_ERASE; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Enable page erase.*/ - devp->flash->CR |= FLASH_CR_PER; - -#if defined(FLASH_CR_BKER) - /* If dual bank is active then setup relevant bank. */ - if (stm32_flash_dual_bank(devp)) { - if (sector < (bank->sectors_count / 2)) { - /* First bank.*/ - devp->flash->CR &= ~FLASH_CR_BKER; - } - else { - /* Second bank. Adjust sector index. */ - sector -= (bank->sectors_count / 2); - devp->flash->CR |= FLASH_CR_BKER; - } - } -#endif - - /* Mask off the page selection bits.*/ - devp->flash->CR &= ~FLASH_CR_PNB; - - /* Set the page selection bits.*/ - devp->flash->CR |= sector << FLASH_CR_PNB_Pos; - - /* Start the erase.*/ - devp->flash->CR |= FLASH_CR_STRT; - - return FLASH_NO_ERROR; -} - -/** - * @brief Queries the driver for erase operation progress. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[out] msec recommended time, in milliseconds, that - * should be spent before calling this - * function again, can be @p NULL - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_ERASE if the erase operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @api - */ -flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err; - - /* If there is an erase in progress then the device must be checked.*/ - if (devp->state == FLASH_ERASE) { - - /* Checking for operation in progress.*/ - if ((devp->flash->SR & FLASH_SR_BSY1) == 0U) { - - /* Disabling the various erase control bits.*/ - devp->flash->CR &= ~(FLASH_CR_MER1 | -#if defined(FLASH_CR_MER2) - FLASH_CR_MER2 | -#endif - FLASH_CR_PER); - - /* No operation in progress, checking for errors.*/ - err = stm32_flash_check_errors(devp); - - /* Back to ready state.*/ - devp->state = FLASH_READY; - } - else { - /* Recommended time before polling again. This is a simplified - implementation.*/ - if (msec != NULL) { - *msec = (uint32_t)STM32_FLASH_WAIT_TIME_MS; - } - - err = FLASH_BUSY_ERASING; - } - } - else { - err = FLASH_NO_ERROR; - } - - return err; -} - -/** - * @brief Returns the erase state of a sector. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] sector sector to be verified - * @return An error code. - * @retval FLASH_NO_ERROR if the sector is erased. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_VERIFY if the verify operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { - EFlashDriver *devp = (EFlashDriver *)instance; - uint32_t *address; - const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); - flash_error_t err = FLASH_NO_ERROR; - unsigned i; - - osalDbgCheck(instance != NULL); - osalDbgCheck(sector < bank->sectors_count); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No verifying while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* Address of the sector in the selected bank.*/ - address = (uint32_t *)(bank->address + - flashGetSectorOffset(getBaseFlash(devp), sector)); - - /* FLASH_READ state while the operation is performed.*/ - devp->state = FLASH_READ; - - /* Scanning the sector space.*/ - uint32_t sector_size = flashGetSectorSize(getBaseFlash(devp), sector); - for (i = 0U; i < sector_size / sizeof(uint32_t); i++) { - if (*address != 0xFFFFFFFFU) { - err = FLASH_ERROR_VERIFY; - break; - } - address++; - } - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -#endif /* HAL_USE_EFL == TRUE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_efl_lld.c + * @brief STM32G07/8nxx Embedded Flash subsystem low level driver source. + * + * @addtogroup HAL_EFL + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define STM32_FLASH_LINE_SIZE 8U +#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U) + +#define FLASH_PDKEY1 0x04152637U +#define FLASH_PDKEY2 0xFAFBFCFDU + +#define FLASH_KEY1 0x45670123U +#define FLASH_KEY2 0xCDEF89ABU + +#define FLASH_OPTKEY1 0x08192A3BU +#define FLASH_OPTKEY2 0x4C5D6E7FU + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EFL1 driver identifier. + */ +EFlashDriver EFLD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* The descriptor for 64K devices. */ +static const flash_descriptor_t efl_lld_size1[STM32_FLASH_NUMBER_OF_BANKS] = { + { /* Bank 1. */ + .attributes = FLASH_ATTR_ERASED_IS_ONE | + FLASH_ATTR_MEMORY_MAPPED | + FLASH_ATTR_ECC_CAPABLE | + FLASH_ATTR_ECC_ZERO_LINE_CAPABLE, + .page_size = STM32_FLASH_LINE_SIZE, + .sectors_count = STM32_FLASH_SECTORS_TOTAL_64K, + .sectors = NULL, + .sectors_size = STM32_FLASH_SECTOR_SIZE_64K, + .address = (uint8_t *)FLASH_BASE, + .size = STM32_FLASH_SIZE_64K * STM32_FLASH_SIZE_SCALE + } +}; + +/* The descriptor for 128K devices. */ +static const flash_descriptor_t efl_lld_size2[STM32_FLASH_NUMBER_OF_BANKS] = { + { /* Bank 1. */ + .attributes = FLASH_ATTR_ERASED_IS_ONE | + FLASH_ATTR_MEMORY_MAPPED | + FLASH_ATTR_ECC_CAPABLE | + FLASH_ATTR_ECC_ZERO_LINE_CAPABLE, + .page_size = STM32_FLASH_LINE_SIZE, + .sectors_count = STM32_FLASH_SECTORS_TOTAL_128K, + .sectors = NULL, + .sectors_size = STM32_FLASH_SECTOR_SIZE_128K, + .address = (uint8_t *)FLASH_BASE, + .size = STM32_FLASH_SIZE_128K * STM32_FLASH_SIZE_SCALE + } +}; + +/* Table describing possible flash sizes and descriptors for this device. */ +static const efl_lld_size_t efl_lld_flash_sizes[] = { + { + .desc = efl_lld_size1 + }, + { + .desc = efl_lld_size2 + } +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static inline void stm32_flash_lock(EFlashDriver *eflp) { + + eflp->flash->CR |= FLASH_CR_LOCK; +} + +static inline void stm32_flash_unlock(EFlashDriver *eflp) { + + eflp->flash->KEYR |= FLASH_KEY1; + eflp->flash->KEYR |= FLASH_KEY2; +} + +static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) { + + eflp->flash->CR |= FLASH_CR_PG; +} + +static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) { + + eflp->flash->CR &= ~FLASH_CR_PG; +} + +static inline void stm32_flash_clear_status(EFlashDriver *eflp) { + + eflp->flash->SR = 0x0000FFFFU; +} + +static inline void stm32_flash_wait_busy(EFlashDriver *eflp) { + + /* Wait for busy bit clear.*/ + while ((eflp->flash->SR & FLASH_SR_BSY1) != 0U) { + } +} + +static inline size_t stm32_flash_get_size(void) { + return *(uint16_t*)((uint32_t) STM32_FLASH_SIZE_REGISTER) * STM32_FLASH_SIZE_SCALE; +} + +static inline bool stm32_flash_dual_bank(EFlashDriver *eflp) { + +#if STM32_FLASH_NUMBER_OF_BANKS > 1 +#error "Device settings incorrectly configured - single bank mode only supported" +#endif + (void)eflp; + return false; +} + +static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) { + uint32_t sr = eflp->flash->SR; + + /* Clearing error conditions.*/ + eflp->flash->SR = sr & 0x0000FFFFU; + + /* Some errors are only caught by assertion.*/ + osalDbgAssert((sr & (FLASH_SR_FASTERR | + FLASH_SR_MISERR | + FLASH_SR_SIZERR)) == 0U, "unexpected flash error"); + + /* Decoding relevant errors.*/ + if ((sr & FLASH_SR_WRPERR) != 0U) { + return FLASH_ERROR_HW_FAILURE; + } + + if ((sr & (FLASH_SR_PGAERR | FLASH_SR_PROGERR | FLASH_SR_OPERR)) != 0U) { + return eflp->state == FLASH_PGM ? FLASH_ERROR_PROGRAM : FLASH_ERROR_ERASE; + } + + return FLASH_NO_ERROR; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level Embedded Flash driver initialization. + * + * @notapi + */ +void efl_lld_init(void) { + + /* Driver initialization.*/ + eflObjectInit(&EFLD1); + EFLD1.flash = FLASH; + /* Find the size of the flash and set descriptor reference. */ + uint8_t i; + for (i = 0; i < (sizeof(efl_lld_flash_sizes) / sizeof(efl_lld_size_t)); i++) { + if (efl_lld_flash_sizes[i].desc->size == stm32_flash_get_size()) { + EFLD1.descriptor = efl_lld_flash_sizes[i].desc; + if (stm32_flash_dual_bank(&EFLD1)) { + /* Point to the dual bank descriptor. */ + EFLD1.descriptor++; + } + return; + } + } + osalDbgAssert(false, "invalid flash configuration"); +} + +/** + * @brief Configures and activates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_start(EFlashDriver *eflp) { + stm32_flash_unlock(eflp); + FLASH->CR = 0x00000000U; +} + +/** + * @brief Deactivates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_stop(EFlashDriver *eflp) { + + stm32_flash_lock(eflp); +} + +/** + * @brief Gets the flash descriptor structure. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @return A flash device descriptor. + * @retval Pointer to single bank if DBM not enabled. + * @retval Pointer to bank1 if DBM enabled. + * + * @notapi + */ +const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { + EFlashDriver *devp = (EFlashDriver *)instance; + return devp->descriptor; +} + +/** + * @brief Read operation. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] offset offset within full flash address space + * @param[in] n number of bytes to be read + * @param[out] rp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_READ if the read operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); + + const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); + osalDbgCheck((size_t)offset + n <= (size_t)bank->size); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No reading while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_READ state while the operation is performed.*/ + devp->state = FLASH_READ; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Actual read implementation.*/ + memcpy((void *)rp, (const void *)efl_lld_get_descriptor(instance)->address + + offset, n); + + /* Checking for errors after reading.*/ + if ((devp->flash->SR & FLASH_SR_RDERR) != 0U) { + err = FLASH_ERROR_READ; + } + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; + +} + +/** + * @brief Program operation. + * @note The device supports ECC, it is only possible to write erased + * pages once except when writing all zeroes. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] offset offset within full flash address space + * @param[in] n number of bytes to be programmed + * @param[in] pp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_PROGRAM if the program operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp) { + EFlashDriver *devp = (EFlashDriver *)instance; + const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)bank->size); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No programming while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_PGM; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Enabling PGM mode in the controller.*/ + stm32_flash_enable_pgm(devp); + + /* Actual program implementation.*/ + while (n > 0U) { + volatile uint32_t *address; + + union { + uint32_t w[STM32_FLASH_LINE_SIZE / sizeof (uint32_t)]; + uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)]; + } line; + + /* Unwritten bytes are initialized to all ones.*/ + line.w[0] = 0xFFFFFFFFU; + line.w[1] = 0xFFFFFFFFU; + + /* Programming address aligned to flash lines.*/ + address = (volatile uint32_t *)(bank->address + + (offset & ~STM32_FLASH_LINE_MASK)); + + /* Copying data inside the prepared line.*/ + do { + line.b[offset & STM32_FLASH_LINE_MASK] = *pp; + offset++; + n--; + pp++; + } + while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U)); + + /* Programming line.*/ + address[0] = line.w[0]; + address[1] = line.w[1]; + stm32_flash_wait_busy(devp); + err = stm32_flash_check_errors(devp); + if (err != FLASH_NO_ERROR) { + break; + } + } + + /* Disabling PGM mode in the controller.*/ + stm32_flash_disable_pgm(devp); + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +/** + * @brief Starts a whole-device erase operation. + * @note This function only erases bank 2 if it is present. Bank 1 is not + * allowed since it is normally where the primary program is located. + * Pages on bank 1 can be individually erased. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_all(void *instance) { + EFlashDriver *devp = (EFlashDriver *)instance; + + osalDbgCheck(instance != NULL); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No erasing while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + +#if defined(FLASH_CR_MER2) + /* If dual bank is active then mass erase bank2. */ + if (stm32_flash_dual_bank(devp)) { + + /* FLASH_ERASE state while the operation is performed.*/ + devp->state = FLASH_ERASE; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + devp->flash->CR |= FLASH_CR_MER2; + devp->flash->CR |= FLASH_CR_STRT; + return FLASH_NO_ERROR; + } +#endif + + /* Mass erase not allowed. */ + return FLASH_ERROR_UNIMPLEMENTED; +} + +/** + * @brief Starts an sector erase operation. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] sector sector to be erased + * this is an index within the total sectors + * in a flash bank + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < bank->sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No erasing while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_ERASE; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Enable page erase.*/ + devp->flash->CR |= FLASH_CR_PER; + +#if defined(FLASH_CR_BKER) + /* If dual bank is active then setup relevant bank. */ + if (stm32_flash_dual_bank(devp)) { + if (sector < (bank->sectors_count / 2)) { + /* First bank.*/ + devp->flash->CR &= ~FLASH_CR_BKER; + } + else { + /* Second bank. Adjust sector index. */ + sector -= (bank->sectors_count / 2); + devp->flash->CR |= FLASH_CR_BKER; + } + } +#endif + + /* Mask off the page selection bits.*/ + devp->flash->CR &= ~FLASH_CR_PNB; + + /* Set the page selection bits.*/ + devp->flash->CR |= sector << FLASH_CR_PNB_Pos; + + /* Start the erase.*/ + devp->flash->CR |= FLASH_CR_STRT; + + return FLASH_NO_ERROR; +} + +/** + * @brief Queries the driver for erase operation progress. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[out] msec recommended time, in milliseconds, that + * should be spent before calling this + * function again, can be @p NULL + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_ERASE if the erase operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @api + */ +flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err; + + /* If there is an erase in progress then the device must be checked.*/ + if (devp->state == FLASH_ERASE) { + + /* Checking for operation in progress.*/ + if ((devp->flash->SR & FLASH_SR_BSY1) == 0U) { + + /* Disabling the various erase control bits.*/ + devp->flash->CR &= ~(FLASH_CR_MER1 | +#if defined(FLASH_CR_MER2) + FLASH_CR_MER2 | +#endif + FLASH_CR_PER); + + /* No operation in progress, checking for errors.*/ + err = stm32_flash_check_errors(devp); + + /* Back to ready state.*/ + devp->state = FLASH_READY; + } + else { + /* Recommended time before polling again. This is a simplified + implementation.*/ + if (msec != NULL) { + *msec = (uint32_t)STM32_FLASH_WAIT_TIME_MS; + } + + err = FLASH_BUSY_ERASING; + } + } + else { + err = FLASH_NO_ERROR; + } + + return err; +} + +/** + * @brief Returns the erase state of a sector. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] sector sector to be verified + * @return An error code. + * @retval FLASH_NO_ERROR if the sector is erased. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_VERIFY if the verify operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + uint32_t *address; + const flash_descriptor_t *bank = efl_lld_get_descriptor(instance); + flash_error_t err = FLASH_NO_ERROR; + unsigned i; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < bank->sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No verifying while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* Address of the sector in the selected bank.*/ + address = (uint32_t *)(bank->address + + flashGetSectorOffset(getBaseFlash(devp), sector)); + + /* FLASH_READ state while the operation is performed.*/ + devp->state = FLASH_READ; + + /* Scanning the sector space.*/ + uint32_t sector_size = flashGetSectorSize(getBaseFlash(devp), sector); + for (i = 0U; i < sector_size / sizeof(uint32_t); i++) { + if (*address != 0xFFFFFFFFU) { + err = FLASH_ERROR_VERIFY; + break; + } + address++; + } + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +#endif /* HAL_USE_EFL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.h b/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.h index 19f4b83cab..1b647abd22 100644 --- a/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.h +++ b/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.h @@ -1,144 +1,144 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_efl_lld.h - * @brief STM32G07/8nxx Embedded Flash subsystem low level driver header. - * - * @addtogroup HAL_EFL - * @{ - */ - -#ifndef HAL_EFL_LLD_H -#define HAL_EFL_LLD_H - -#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name STM32G0xx configuration options - * @{ - */ -/** - * @brief Suggested wait time during erase operations polling. - */ -#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) -#define STM32_FLASH_WAIT_TIME_MS 5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if defined(STM32G070xx) || defined(STM32G071xx) || \ - defined(STM32G081xx) || \ - defined(__DOXYGEN__) - -/* Flash size register. */ -#define STM32_FLASH_SIZE_REGISTER 0x1FFF75E0 -#define STM32_FLASH_SIZE_SCALE 1024U - -/* - * Flash size is organised as 32 or 64 x 2K pages. - * - */ -#define STM32_FLASH_SIZE_64K 64U -#define STM32_FLASH_SIZE_128K 128U -#define STM32_FLASH_SECTORS_TOTAL_64K 32 -#define STM32_FLASH_SECTORS_TOTAL_128K 64 - -/* 64K flash.*/ -#define STM32_FLASH_SECTOR_SIZE_64K ((STM32_FLASH_SIZE_64K \ - * STM32_FLASH_SIZE_SCALE) \ - / STM32_FLASH_SECTORS_TOTAL_64K) -/* 128K flash.*/ -#define STM32_FLASH_SECTOR_SIZE_128K ((STM32_FLASH_SIZE_128K \ - * STM32_FLASH_SIZE_SCALE) \ - / STM32_FLASH_SECTORS_TOTAL_128K) - -#else -#error "This EFL driver does not support the selected device" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/* A flash size declaration. */ -typedef struct { - const flash_descriptor_t* desc; -} efl_lld_size_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the embedded flash driver structure. - */ -#define efl_lld_driver_fields \ - /* Flash registers.*/ \ - FLASH_TypeDef *flash; \ - const flash_descriptor_t *descriptor; - -/** - * @brief Low level fields of the embedded flash configuration structure. - */ -#define efl_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern EFlashDriver EFLD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void efl_lld_init(void); - void efl_lld_start(EFlashDriver *eflp); - void efl_lld_stop(EFlashDriver *eflp); - const flash_descriptor_t *efl_lld_get_descriptor(void *instance); - flash_error_t efl_lld_read(void *instance, flash_offset_t offset, - size_t n, uint8_t *rp); - flash_error_t efl_lld_program(void *instance, flash_offset_t offset, - size_t n, const uint8_t *pp); - flash_error_t efl_lld_start_erase_all(void *instance); - flash_error_t efl_lld_start_erase_sector(void *instance, - flash_sector_t sector); - flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec); - flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EFL == TRUE */ - -#endif /* HAL_EFL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_efl_lld.h + * @brief STM32G07/8nxx Embedded Flash subsystem low level driver header. + * + * @addtogroup HAL_EFL + * @{ + */ + +#ifndef HAL_EFL_LLD_H +#define HAL_EFL_LLD_H + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name STM32G0xx configuration options + * @{ + */ +/** + * @brief Suggested wait time during erase operations polling. + */ +#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) +#define STM32_FLASH_WAIT_TIME_MS 5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if defined(STM32G070xx) || defined(STM32G071xx) || \ + defined(STM32G081xx) || \ + defined(__DOXYGEN__) + +/* Flash size register. */ +#define STM32_FLASH_SIZE_REGISTER 0x1FFF75E0 +#define STM32_FLASH_SIZE_SCALE 1024U + +/* + * Flash size is organised as 32 or 64 x 2K pages. + * + */ +#define STM32_FLASH_SIZE_64K 64U +#define STM32_FLASH_SIZE_128K 128U +#define STM32_FLASH_SECTORS_TOTAL_64K 32 +#define STM32_FLASH_SECTORS_TOTAL_128K 64 + +/* 64K flash.*/ +#define STM32_FLASH_SECTOR_SIZE_64K ((STM32_FLASH_SIZE_64K \ + * STM32_FLASH_SIZE_SCALE) \ + / STM32_FLASH_SECTORS_TOTAL_64K) +/* 128K flash.*/ +#define STM32_FLASH_SECTOR_SIZE_128K ((STM32_FLASH_SIZE_128K \ + * STM32_FLASH_SIZE_SCALE) \ + / STM32_FLASH_SECTORS_TOTAL_128K) + +#else +#error "This EFL driver does not support the selected device" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/* A flash size declaration. */ +typedef struct { + const flash_descriptor_t* desc; +} efl_lld_size_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the embedded flash driver structure. + */ +#define efl_lld_driver_fields \ + /* Flash registers.*/ \ + FLASH_TypeDef *flash; \ + const flash_descriptor_t *descriptor; + +/** + * @brief Low level fields of the embedded flash configuration structure. + */ +#define efl_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern EFlashDriver EFLD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void efl_lld_init(void); + void efl_lld_start(EFlashDriver *eflp); + void efl_lld_stop(EFlashDriver *eflp); + const flash_descriptor_t *efl_lld_get_descriptor(void *instance); + flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp); + flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp); + flash_error_t efl_lld_start_erase_all(void *instance); + flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector); + flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec); + flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EFL == TRUE */ + +#endif /* HAL_EFL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/hal_lld.c b/os/hal/ports/STM32/STM32G0xx/hal_lld.c index 960cad5c2e..b4befc9cbf 100644 --- a/os/hal/ports/STM32/STM32G0xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32G0xx/hal_lld.c @@ -1,253 +1,253 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx+/hal_lld.c - * @brief STM32G0xx+ HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32l4xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing RTC clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - - /* Low speed output mode.*/ - RCC->BDCR |= STM32_LSCOSEL; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals.*/ - rccResetAHB(~0); - rccResetAPBR1(~RCC_APBRSTR1_PWRRST); - rccResetAPBR2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector settings.*/ - PWR->CR2 = STM32_PWR_CR2; -} - -/** - * @brief STM32G0xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ -#if defined(HAL_USE_RTC) && defined(RCC_APBENR1_RTCAPBEN) - RCC->APBENR1 = RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; -#else - RCC->APBENR1 = RCC_APBENR1_PWREN; -#endif - - /* Core voltage setup.*/ - PWR->CR1 = STM32_VOS; - while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ - ; /* stable. */ - -#if STM32_HSI16_ENABLED - /* HSI activation.*/ - RCC->CR |= RCC_CR_HSION | STM32_HSIDIV; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Wait until HSI16 is stable. */ -#endif - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Wait until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Wait until LSI is stable. */ -#endif - - /* Backup domain access enabled and left open.*/ - PWR->CR1 |= PWR_CR1_DBP; - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - while (rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Waits until LSE is stable or times out. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLLM and PLLSRC are common to all PLLs.*/ - RCC->PLLCFGR = STM32_PLLR | STM32_PLLREN | - STM32_PLLQ | STM32_PLLQEN | - STM32_PLLP | STM32_PLLPEN | - STM32_PLLN | STM32_PLLM | - STM32_PLLSRC; -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLRDY) == 0) - ; -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_PPRE | STM32_HPRE; - - /* CCIPR register initialization, note, must take care of the _OFF - pseudo settings.*/ - RCC->CCIPR = STM32_ADCSEL | STM32_RNGDIV | STM32_RNGSEL | - STM32_TIM15SEL | STM32_TIM1SEL | STM32_LPTIM2SEL | - STM32_LPTIM1SEL | STM32_I2S1SEL | STM32_I2C1SEL | - STM32_CECSEL | STM32_USART2SEL | STM32_USART1SEL | - STM32_LPUART1SEL; - - /* Set flash WS's for SYSCLK source */ - FLASH->ACR = FLASH_ACR_DBG_SWEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | - STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured SYSCLK source if it is different from HSI16.*/ -#if STM32_SW != STM32_SW_HSISYS - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - /* Wait until SYSCLK is stable.*/ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 3)) - ; -#endif - -#endif /* STM32_NO_INIT */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPBR2(RCC_APBENR2_SYSCFGEN, true); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx+/hal_lld.c + * @brief STM32G0xx+ HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32l4xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing RTC clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int rusefiLseCounter = 0; + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + + /* Low speed output mode.*/ + RCC->BDCR |= STM32_LSCOSEL; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals.*/ + rccResetAHB(~0); + rccResetAPBR1(~RCC_APBRSTR1_PWRRST); + rccResetAPBR2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector settings.*/ + PWR->CR2 = STM32_PWR_CR2; +} + +/** + * @brief STM32G0xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ +#if defined(HAL_USE_RTC) && defined(RCC_APBENR1_RTCAPBEN) + RCC->APBENR1 = RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; +#else + RCC->APBENR1 = RCC_APBENR1_PWREN; +#endif + + /* Core voltage setup.*/ + PWR->CR1 = STM32_VOS; + while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ + ; /* stable. */ + +#if STM32_HSI16_ENABLED + /* HSI activation.*/ + RCC->CR |= RCC_CR_HSION | STM32_HSIDIV; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Wait until HSI16 is stable. */ +#endif + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Wait until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Wait until LSI is stable. */ +#endif + + /* Backup domain access enabled and left open.*/ + PWR->CR1 |= PWR_CR1_DBP; + +#if STM32_LSE_ENABLED + int rusefiLseCounter = 0; + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + while (rusefiLseCounter++ < FOME_STM32_LSE_WAIT_MAX + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Waits until LSE is stable or times out. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLLM and PLLSRC are common to all PLLs.*/ + RCC->PLLCFGR = STM32_PLLR | STM32_PLLREN | + STM32_PLLQ | STM32_PLLQEN | + STM32_PLLP | STM32_PLLPEN | + STM32_PLLN | STM32_PLLM | + STM32_PLLSRC; +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLRDY) == 0) + ; +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_PPRE | STM32_HPRE; + + /* CCIPR register initialization, note, must take care of the _OFF + pseudo settings.*/ + RCC->CCIPR = STM32_ADCSEL | STM32_RNGDIV | STM32_RNGSEL | + STM32_TIM15SEL | STM32_TIM1SEL | STM32_LPTIM2SEL | + STM32_LPTIM1SEL | STM32_I2S1SEL | STM32_I2C1SEL | + STM32_CECSEL | STM32_USART2SEL | STM32_USART1SEL | + STM32_LPUART1SEL; + + /* Set flash WS's for SYSCLK source */ + FLASH->ACR = FLASH_ACR_DBG_SWEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | + STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured SYSCLK source if it is different from HSI16.*/ +#if STM32_SW != STM32_SW_HSISYS + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + /* Wait until SYSCLK is stable.*/ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 3)) + ; +#endif + +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPBR2(RCC_APBENR2_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/hal_lld.h b/os/hal/ports/STM32/STM32G0xx/hal_lld.h index f9db68820e..53e07872ce 100644 --- a/os/hal/ports/STM32/STM32G0xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32G0xx/hal_lld.h @@ -1,1591 +1,1599 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx/hal_lld.h - * @brief STM32G0xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32G070xx. - * - STM32G071xx, STM32G081xx. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32G070xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32G0 Entry-level Value Line" - -#elif defined(STM32G071xx) -#define PLATFORM_NAME "STM32G0 Entry-level" - -#elif defined(STM32G081xx) -#define PLATFORM_NAME "STM32G0 Entry-level with Crypto" - -#else -#error "STM32G0 device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32G0XX) || defined(__DOXYGEN__) -#define STM32G0XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSI16CLK 16000000U /**< 16MHz internal clock. */ -#define STM32_LSICLK 32000U /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR1 register bits definitions - * @{ - */ -#define STM32_VOS_MASK (3U << 9U) /**< Core voltage mask. */ -#define STM32_VOS_RANGE1 (1U << 9U) /**< Core voltage 1.2 Volts. */ -#define STM32_VOS_RANGE2 (2U << 9U) /**< Core voltage 1.0 Volts. */ -/** @} */ - -/** - * @name PWR_CR2 register bits definitions - * @{ - */ -#define STM32_PVDE_DISABLED (0U << 1U) /**< PVD enable bit off. */ -#define STM32_PVDE_ENABLED (1U << 1U) /**< PVD enable bit on. */ - -#define STM32_PVDFT_MASK (7U << 1U) /**< PVDFT bits mask. */ -#define STM32_PVDFT(n) ((n) << 1U) /**< PVDFT level. */ -#define STM32_PVDFT_LEV0 STM32_PVDFT(0U) /**< PVDFT level 0. */ -#define STM32_PVDFT_LEV1 STM32_PVDFT(1U) /**< PVDFT level 1. */ -#define STM32_PVDFT_LEV2 STM32_PVDFT(2U) /**< PVDFT level 2. */ -#define STM32_PVDFT_LEV3 STM32_PVDFT(3U) /**< PVDFT level 3. */ -#define STM32_PVDFT_LEV4 STM32_PVDFT(4U) /**< PVDFT level 4. */ -#define STM32_PVDFT_LEV5 STM32_PVDFT(5U) /**< PVDFT level 5. */ -#define STM32_PVDFT_LEV6 STM32_PVDFT(6U) /**< PVDFT level 6. */ -#define STM32_PVDFT_LEV7 STM32_PVDFT(7U) /**< PVDFT level 7. */ - -#define STM32_PVDRT_MASK (7U << 4U) /**< PVDRT bits mask. */ -#define STM32_PVDRT(n) ((n) << 4U) /**< PVDRT level. */ -#define STM32_PVDRT_LEV0 STM32_PVDRT(0U) /**< PVDRT level 0. */ -#define STM32_PVDRT_LEV1 STM32_PVDRT(1U) /**< PVDRT level 1. */ -#define STM32_PVDRT_LEV2 STM32_PVDRT(2U) /**< PVDRT level 2. */ -#define STM32_PVDRT_LEV3 STM32_PVDRT(3U) /**< PVDRT level 3. */ -#define STM32_PVDRT_LEV4 STM32_PVDRT(4U) /**< PVDRT level 4. */ -#define STM32_PVDRT_LEV5 STM32_PVDRT(5U) /**< PVDRT level 5. */ -#define STM32_PVDRT_LEV6 STM32_PVDRT(6U) /**< PVDRT level 6. */ -#define STM32_PVDRT_LEV7 STM32_PVDRT(7U) /**< PVDRT level 7. */ -/** @} */ - -/** - * @name RCC_CR register bits definitions - * @{ - */ -#define STM32_HSIDIV_MASK (7U << 11U) /**< HSIDIV field mask. */ -#define STM32_HSIDIV_FIELD(n) ((n) << 11U) /**< HSIDIV field value. */ -#define STM32_HSIDIV_1 STM32_HSIDIV_FIELD(0U) -#define STM32_HSIDIV_2 STM32_HSIDIV_FIELD(1U) -#define STM32_HSIDIV_4 STM32_HSIDIV_FIELD(2U) -#define STM32_HSIDIV_8 STM32_HSIDIV_FIELD(3U) -#define STM32_HSIDIV_16 STM32_HSIDIV_FIELD(4U) -#define STM32_HSIDIV_32 STM32_HSIDIV_FIELD(5U) -#define STM32_HSIDIV_64 STM32_HSIDIV_FIELD(6U) -#define STM32_HSIDIV_128 STM32_HSIDIV_FIELD(7U) -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (7U << 0U) /**< SW field mask. */ -#define STM32_SW_HSISYS (0U << 0U) /**< SYSCLK source is HSISYS. */ -#define STM32_SW_HSE (1U << 0U) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLLRCLK (2U << 0U) /**< SYSCLK source is PLL. */ -#define STM32_SW_LSI (3U << 0U) /**< SYSCLK source is LSI. */ -#define STM32_SW_LSE (4U << 0U) /**< SYSCLK source is LSE. */ - -#define STM32_HPRE_MASK (15U << 8U) /**< HPRE field mask. */ -#define STM32_HPRE_FIELD(n) ((n) << 8U) /**< HPRE field value. */ -#define STM32_HPRE_DIV1 STM32_HPRE_FIELD(0U) -#define STM32_HPRE_DIV2 STM32_HPRE_FIELD(8U) -#define STM32_HPRE_DIV4 STM32_HPRE_FIELD(9U) -#define STM32_HPRE_DIV8 STM32_HPRE_FIELD(10U) -#define STM32_HPRE_DIV16 STM32_HPRE_FIELD(11U) -#define STM32_HPRE_DIV64 STM32_HPRE_FIELD(12U) -#define STM32_HPRE_DIV128 STM32_HPRE_FIELD(13U) -#define STM32_HPRE_DIV256 STM32_HPRE_FIELD(14U) -#define STM32_HPRE_DIV512 STM32_HPRE_FIELD(15U) - -#define STM32_PPRE_MASK (7U << 12U) /**< PPRE field mask. */ -#define STM32_PPRE_FIELD(n) ((n) << 12U) /**< PPRE field value. */ -#define STM32_PPRE_DIV1 STM32_PPRE_FIELD(0U) -#define STM32_PPRE_DIV2 STM32_PPRE_FIELD(4U) -#define STM32_PPRE_DIV4 STM32_PPRE_FIELD(5U) -#define STM32_PPRE_DIV8 STM32_PPRE_FIELD(6U) -#define STM32_PPRE_DIV16 STM32_PPRE_FIELD(7U) - -#define STM32_MCOSEL_MASK (7U << 24U) /**< MCOSEL field mask. */ -#define STM32_MCOSEL_NOCLOCK (0U << 24U) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1U << 24U) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI16 (3U << 24U) /**< HSI16 clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4U << 24U) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLRCLK (5U << 24U) /**< PLLR clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6U << 24U) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7U << 24U) /**< LSE clock on MCO pin. */ - -#define STM32_MCOPRE_MASK (7U << 28U) /**< MCOPRE field mask. */ -#define STM32_MCOPRE_FIELD(n) ((n) << 28U)/**< MCOPRE field value */ -#define STM32_MCOPRE_DIV1 STM32_MCOPRE_FIELD(0U) -#define STM32_MCOPRE_DIV2 STM32_MCOPRE_FIELD(1U) -#define STM32_MCOPRE_DIV4 STM32_MCOPRE_FIELD(2U) -#define STM32_MCOPRE_DIV8 STM32_MCOPRE_FIELD(3U) -#define STM32_MCOPRE_DIV16 STM32_MCOPRE_FIELD(4U) -#define STM32_MCOPRE_DIV32 STM32_MCOPRE_FIELD(5U) -#define STM32_MCOPRE_DIV64 STM32_MCOPRE_FIELD(6U) -#define STM32_MCOPRE_DIV128 STM32_MCOPRE_FIELD(7U) -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CCIPR register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3U << 0U) /**< USART1SEL mask. */ -#define STM32_USART1SEL_PCLK (0U << 0U) /**< USART1 source is PCLK. */ -#define STM32_USART1SEL_SYSCLK (1U << 0U) /**< USART1 source is SYSCLK. */ -#define STM32_USART1SEL_HSI16 (2U << 0U) /**< USART1 source is HSI16. */ -#define STM32_USART1SEL_LSE (3U << 0U) /**< USART1 source is LSE. */ - -#define STM32_USART2SEL_MASK (3U << 2U) /**< USART2 mask. */ -#define STM32_USART2SEL_PCLK (0U << 2U) /**< USART2 source is PCLK. */ -#define STM32_USART2SEL_SYSCLK (1U << 2U) /**< USART2 source is SYSCLK. */ -#define STM32_USART2SEL_HSI16 (2U << 2U) /**< USART2 source is HSI16. */ -#define STM32_USART2SEL_LSE (3U << 2U) /**< USART2 source is LSE. */ - -#define STM32_CECSEL_MASK (1U << 6U) /**< CEC mask. */ -#define STM32_CECSEL_HSI16DIV (0U << 6U) /**< CEC source is HSI16/448. */ -#define STM32_CECSEL_LSE (1U << 6U) /**< CEC source is LSE. */ - -#define STM32_LPUART1SEL_MASK (3U << 10U) /**< LPUART1 mask. */ -#define STM32_LPUART1SEL_PCLK (0U << 10U) /**< LPUART1 source is PCLK. */ -#define STM32_LPUART1SEL_SYSCLK (1U << 10U) /**< LPUART1 source is SYSCLK. */ -#define STM32_LPUART1SEL_HSI16 (2U << 10U) /**< LPUART1 source is HSI16. */ -#define STM32_LPUART1SEL_LSE (3U << 10U) /**< LPUART1 source is LSE. */ - -#define STM32_I2C1SEL_MASK (3U << 12U) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK (0U << 12U) /**< I2C1 source is PCLK. */ -#define STM32_I2C1SEL_SYSCLK (1U << 12U) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI16 (2U << 12U) /**< I2C1 source is HSI16. */ - -#define STM32_I2S1SEL_MASK (3U << 14U) /**< I2S1SEL mask. */ -#define STM32_I2S1SEL_SYSCLK (0U << 14U) /**< I2S1 source is SYSCLK. */ -#define STM32_I2S1SEL_PLLPCLK (1U << 14U) /**< I2S1 source is PLLPCLK. */ -#define STM32_I2S1SEL_HSI16 (2U << 14U) /**< I2S1 source is HSI16. */ -#define STM32_I2S1SEL_CKIN (3U << 14U) /**< I2S1 source is CKIN. */ - -#define STM32_LPTIM1SEL_MASK (3U << 18U) /**< LPTIM1SEL mask. */ -#define STM32_LPTIM1SEL_PCLK (0U << 18U) /**< LPTIM1 source is PCLK. */ -#define STM32_LPTIM1SEL_LSI (1U << 18U) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_HSI16 (2U << 18U) /**< LPTIM1 source is HSI16. */ -#define STM32_LPTIM1SEL_LSE (3U << 18U) /**< LPTIM1 source is LSE. */ - -#define STM32_LPTIM2SEL_MASK (3U << 20U) /**< LPTIM2SEL mask. */ -#define STM32_LPTIM2SEL_PCLK (0U << 20U) /**< LPTIM2 source is PCLK. */ -#define STM32_LPTIM2SEL_LSI (1U << 20U) /**< LPTIM2 source is LSI. */ -#define STM32_LPTIM2SEL_HSI16 (2U << 20U) /**< LPTIM2 source is HSI16. */ -#define STM32_LPTIM2SEL_LSE (3U << 20U) /**< LPTIM2 source is LSE. */ - -#define STM32_TIM1SEL_MASK (1U << 22U) /**< TIM1SEL mask. */ -#define STM32_TIM1SEL_TIMPCLK (0U << 22U) /**< TIM1SEL source is TIMPCLK. */ -#define STM32_TIM1SEL_PLLQCLK (1U << 22U) /**< TIM1SEL source is PLLQCLK. */ - -#define STM32_TIM15SEL_MASK (1U << 24U) /**< TIM15SEL mask. */ -#define STM32_TIM15SEL_TIMPCLK (0U << 24U) /**< TIM15SEL source is TIMPCLK.*/ -#define STM32_TIM15SEL_PLLQCLK (1U << 24U) /**< TIM15SEL source is PLLQCLK.*/ - -#define STM32_RNGSEL_MASK (3U << 26U) /**< RNGSEL mask. */ -#define STM32_RNGSEL_NOCLOCK (0U << 26U) /**< RNG source is disabled. */ -#define STM32_RNGSEL_HSI16 (1U << 26U) /**< RNG source is HSI16. */ -#define STM32_RNGSEL_SYSCLK (2U << 26U) /**< RNG source is SYSCLK. */ -#define STM32_RNGSEL_PLLQCLK (3U << 26U) /**< RNG source is PLLQCLK. */ - -#define STM32_RNGDIV_MASK (3U << 28U) /**< RNGDIV field mask. */ -#define STM32_RNGDIV_FIELD(n) ((n) << 28U)/**< RNGDIV field value */ -#define STM32_RNGDIV_1 STM32_RNGDIV_FIELD(0U) -#define STM32_RNGDIV_2 STM32_RNGDIV_FIELD(1U) -#define STM32_RNGDIV_4 STM32_RNGDIV_FIELD(2U) -#define STM32_RNGDIV_8 STM32_RNGDIV_FIELD(3U) - -#define STM32_ADCSEL_MASK (3U << 30U) /**< ADCSEL mask. */ -#define STM32_ADCSEL_SYSCLK (0U << 30U) /**< ADC source is SYSCLK. */ -#define STM32_ADCSEL_PLLPCLK (1U << 30U) /**< ADC source is PLLPCLK. */ -#define STM32_ADCSEL_HSI16 (2U << 30U) /**< ADC source is HSI16. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3U << 8U) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0U << 8U) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1U << 8U) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2U << 8U) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3U << 8U) /**< RTC source is HSE divided. */ - -#define STM32_LSCOSEL_MASK (3U << 24U) /**< LSCO pin clock source. */ -#define STM32_LSCOSEL_NOCLOCK (0U << 24U) /**< No clock on LSCO pin. */ -#define STM32_LSCOSEL_LSI (1U << 24U) /**< LSI on LSCO pin. */ -#define STM32_LSCOSEL_LSE (3U << 24U) /**< LSE on LSCO pin. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_RANGE1 -#endif - -/** - * @brief PWR CR2 register initialization value. - */ -#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) -#define STM32_PWR_CR2 (STM32_PVDRT_LEV0 | \ - STM32_PVDFT_LEV0 | \ - STM32_PVDE_DISABLED) -#endif - -/** - * @brief HSI16 divider value. - * @note The allowed values are 1, 2, 4, 8, 16, 32, 64, 128. - */ -#if !defined(STM32_HSIDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_HSIDIV_VALUE 1 -#endif - -/** - * @brief Enables or disables the HSI16 clock source. - */ -#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 64MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLLRCLK -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 64MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 1..8. - * @note The default value is calculated for a 64MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 2 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 8..86. - * @note The default value is calculated for a 64MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 16 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2..32. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 -#endif - -/** - * @brief PLLQ divider value. - * @note The allowed values are 2..8. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 4 -#endif - -/** - * @brief PLLR divider value. - * @note The allowed values are 2..8. - * @note The default value is calculated for a 64MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLR_VALUE 2 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 64MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB prescaler value. - */ -#if !defined(STM32_PPRE) || defined(__DOXYGEN__) -#define STM32_PPRE STM32_PPRE_DIV1 -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief LSCO clock source. - */ -#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#endif - -/** - * @brief LPUART1 clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#endif - -/** - * @brief CEC clock source. - */ -#if !defined(STM32_CECSEL) || defined(__DOXYGEN__) -#define STM32_CECSEL STM32_CECSEL_HSI16DIV -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_PCLK -#endif - -/** - * @brief I2S1 clock source. - */ -#if !defined(STM32_I2S1SEL) || defined(__DOXYGEN__) -#define STM32_I2S1SEL STM32_I2S1SEL_SYSCLK -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK -#endif - -/** - * @brief LPTIM2 clock source. - */ -#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK -#endif - -/** - * @brief TIM1 clock source. - */ -#if !defined(STM32_TIM1SEL) || defined(__DOXYGEN__) -#define STM32_TIM1SEL STM32_TIM1SEL_TIMPCLK -#endif - -/** - * @brief TIM15 clock source. - */ -#if !defined(STM32_TIM15SEL) || defined(__DOXYGEN__) -#define STM32_TIM15SEL STM32_TIM15SEL_TIMPCLK -#endif - -/** - * @brief RNG clock source. - */ -#if !defined(STM32_RNGSEL) || defined(__DOXYGEN__) -#define STM32_RNGSEL STM32_RNGSEL_HSI16 -#endif - -/** - * @brief RNG divider value. - */ -#if !defined(STM32_RNGDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_RNGDIV_VALUE 1 -#endif - -/** - * @brief ADC clock source. - */ -#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) -#define STM32_ADCSEL STM32_ADCSEL_PLLPCLK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32G0xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G0xx_MCUCONF not defined" -#endif - -#if defined(STM32G070xx) && !defined(STM32G070_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G070_MCUCONF not defined" - -#elif defined(STM32G071xx) && !defined(STM32G071_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G071_MCUCONF not defined" - -#elif defined(STM32G081xx) && !defined(STM32G081_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G071_MCUCONF not defined" - -#endif - -/* - * Board files sanity checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif - -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) -/** - * @name System Limits - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency. - */ -#define STM32_SYSCLK_MAX 64000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 48000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 8000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 2660000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 344000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 64000000 - -/** - * @brief Maximum PLL-P output clock frequency. - */ -#define STM32_PLLP_MAX 128000000 - -/** - * @brief Minimum PLL-P output clock frequency. - */ -#define STM32_PLLP_MIN 3090000 - -/** - * @brief Maximum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MAX 128000000 - -/** - * @brief Minimum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MIN 12000000 - -/** - * @brief Maximum PLL-R output clock frequency. - */ -#define STM32_PLLR_MAX 64000000 - -/** - * @brief Minimum PLL-R output clock frequency. - */ -#define STM32_PLLR_MIN 12000000 - -/** - * @brief Maximum APB clock frequency. - */ -#define STM32_PCLK_MAX 64000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 350000000 -/** @} */ - -/** - * @name Flash Wait states - * @{ - */ -#define STM32_0WS_THRESHOLD 24000000 -#define STM32_1WS_THRESHOLD 48000000 -#define STM32_2WS_THRESHOLD 64000000 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -/** @} */ - -#elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 16000000 -#define STM32_HSECLK_MAX 16000000 -#define STM32_HSECLK_BYP_MAX 16000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2660000 -#define STM32_PLLVCO_MAX 128000000 -#define STM32_PLLVCO_MIN 96000000 -#define STM32_PLLP_MAX 40000000 -#define STM32_PLLP_MIN 3090000 -#define STM32_PLLQ_MAX 32000000 -#define STM32_PLLQ_MIN 12000000 -#define STM32_PLLR_MAX 16000000 -#define STM32_PLLR_MIN 12000000 -#define STM32_PCLK_MAX 16000000 -#define STM32_ADCCLK_MAX 16000000 - -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_1WS_THRESHOLD 16000000 -#define STM32_2WS_THRESHOLD 0 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 - -#else -#error "invalid STM32_VOS value specified" -#endif - -/* - * HSI16 related checks. - */ -#if STM32_HSI16_ENABLED -#else /* !STM32_HSI16_ENABLED */ - -#if STM32_SW == STM32_SW_HSISYS -#error "HSI16 not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -/* NOTE: Missing checks on the HSI16 pre-muxes, it is also required for newer - L4 devices.*/ - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16)) -#error "HSI16 not enabled, required by STM32_MCOSEL" -#endif - -#if (STM32_USART1SEL == STM32_USART1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART1SEL" -#endif -#if (STM32_USART2SEL == STM32_USART2SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART2SEL" -#endif -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_LPUART1SEL" -#endif - -#if (STM32_CECSEL == STM32_CECSEL_HSI16DIV) -#error "HSI16 not enabled, required by STM32_CECSEL" -#endif - -#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_I2C1SEL" -#endif -#if (STM32_I2S1SEL == STM32_I2S1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_I2S1SEL" -#endif - -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_LPTIM1SEL" -#endif -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) -#error "HSI16 not enabled, required by STM32_LPTIM2SEL" -#endif - -#if (STM32_RNGSEL == STM32_RNGSEL_HSI16) -#error "HSI16 not enabled, required by STM32_RNGSEL" -#endif - -#if (STM32_ADCSEL == STM32_ADCSEL_HSI16) -#error "HSI16 not enabled, required by STM32_ADCSEL" -#endif - -#endif /* !STM32_HSI16_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - - #if STM32_HSECLK == 0 - #error "HSE frequency not defined" - #else /* STM32_HSECLK != 0 */ - #if defined(STM32_HSE_BYPASS) - #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" - #endif - #else /* !defined(STM32_HSE_BYPASS) */ - #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" - #endif - #endif /* !defined(STM32_HSE_BYPASS) */ - #endif /* STM32_HSECLK != 0 */ - - #else /* !STM32_HSE_ENABLED */ - - #if STM32_SW == STM32_SW_HSE - #error "HSE not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) - #error "HSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV - #error "HSE not enabled, required by STM32_RTCSEL" - #endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - - #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) - #error "LSI not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSI - #error "LSI not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSI - #error "LSI not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - - #if (STM32_LSECLK == 0) - #error "LSE frequency not defined" - #endif - - #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) - #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" - #endif - -#else /* !STM32_LSE_ENABLED */ - - #if STM32_RTCSEL == STM32_RTCSEL_LSE - #error "LSE not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSE - #error "LSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSE - #error "LSE not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief STM32_HSIDIV field. - */ -#if (STM32_HSIDIV_VALUE == 1) || defined(__DOXYGEN__) -#define STM32_HSIDIV STM32_HSIDIV_1 -#elif STM32_HSIDIV_VALUE == 2 -#define STM32_HSIDIV STM32_HSIDIV_2 -#elif STM32_HSIDIV_VALUE == 4 -#define STM32_HSIDIV STM32_HSIDIV_4 -#elif STM32_HSIDIV_VALUE == 8 -#define STM32_HSIDIV STM32_HSIDIV_8 -#elif STM32_HSIDIV_VALUE == 16 -#define STM32_HSIDIV STM32_HSIDIV_16 -#elif STM32_HSIDIV_VALUE == 32 -#define STM32_HSIDIV STM32_HSIDIV_32 -#elif STM32_HSIDIV_VALUE == 64 -#define STM32_HSIDIV STM32_HSIDIV_64 -#elif STM32_HSIDIV_VALUE == 128 -#define STM32_HSIDIV STM32_HSIDIV_128 -#else -#error "invalid STM32_HSIDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 8)) || \ - defined(__DOXYGEN__) -#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) -#else -#error "invalid STM32_PLLM_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 -#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK -#define STM32_PLLCLKIN 0 - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLL input frequency range check. - */ -#if (STM32_PLLCLKIN != 0) && \ - ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_SW == STM32_SW_PLLRCLK) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ - (STM32_TIM1SEL == STM32_TIM1SEL_PLLQCLK) || \ - (STM32_TIM15SEL == STM32_TIM15SEL_PLLQCLK) || \ - (STM32_RNGSEL == STM32_RNGSEL_PLLQCLK) || \ - (STM32_ADCSEL == STM32_ADCSEL_PLLPCLK) || \ - (STM32_I2S1SEL == STM32_I2S1SEL_PLLPCLK) || \ - defined(__DOXYGEN__) - -#if STM32_PLLCLKIN == 0 -#error "PLL activation required but no PLL clock selected" -#endif - -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 86)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 8) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLR field. - */ -#if ((STM32_PLLR_VALUE >= 2) && (STM32_PLLR_VALUE <= 8)) || \ - defined(__DOXYGEN__) -#define STM32_PLLR ((STM32_PLLR_VALUE - 1) << 29) -#else -#error "invalid STM32_PLLR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 8)) || \ - defined(__DOXYGEN__) -#define STM32_PLLQ ((STM32_PLLQ_VALUE - 1) << 25) -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if ((STM32_PLLP_VALUE >= 2) && (STM32_PLLP_VALUE <= 32)) || \ - defined(__DOXYGEN__) -#define STM32_PLLP ((STM32_PLLP_VALUE - 1) << 17) -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLREN field. - */ -#if (STM32_SW == STM32_SW_PLLRCLK) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ - defined(__DOXYGEN__) -#define STM32_PLLREN (1 << 28) -#else -#define STM32_PLLREN (0 << 28) -#endif - -/** - * @brief STM32_PLLQEN field. - */ -#if (STM32_TIM1SEL == STM32_TIM1SEL_PLLQCLK) || \ - (STM32_TIM15SEL == STM32_TIM15SEL_PLLQCLK) || \ - (STM32_RNGSEL == STM32_RNGSEL_PLLQCLK) || \ - defined(__DOXYGEN__) -#define STM32_PLLQEN (1 << 24) -#else -#define STM32_PLLQEN (0 << 24) -#endif - -/** - * @brief STM32_PLLPEN field. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_PLLPCLK) || \ - (STM32_I2S1SEL == STM32_I2S1SEL_PLLPCLK) || \ - defined(__DOXYGEN__) -#define STM32_PLLPEN (1 << 16) -#else -#define STM32_PLLPEN (0 << 16) -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL R output clock frequency. - */ -#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) - -/** - * @brief PLL Q output clock frequency. - */ -#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) - -/** - * @brief PLL P output clock frequency. - */ -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) - -/* - * PLL-R output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/* - * PLL-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLL-P output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/** - * @brief HSISYS clock frequency. - */ -#define STM32_HSISYSCLK (STM32_HSI16CLK / STM32_HSIDIV_VALUE) - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_HSISYSCLK - -#elif (STM32_SW == STM32_SW_HSISYS) -#define STM32_SYSCLK STM32_HSISYSCLK - -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK - -#elif (STM32_SW == STM32_SW_PLLRCLK) -#define STM32_SYSCLK STM32_PLL_R_CLKOUT - -#elif (STM32_SW == STM32_SW_LSI) -#define STM32_SYSCLK STM32_LSICLK - -#elif (STM32_SW == STM32_SW_LSE) -#define STM32_SYSCLK STM32_LSECLK - -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) - -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) - -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) - -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) - -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) - -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) - -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) - -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) - -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) - -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB frequency. - */ -#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK (STM32_HCLK / 1) - -#elif STM32_PPRE == STM32_PPRE_DIV2 -#define STM32_PCLK (STM32_HCLK / 2) - -#elif STM32_PPRE == STM32_PPRE_DIV4 -#define STM32_PCLK (STM32_HCLK / 4) - -#elif STM32_PPRE == STM32_PPRE_DIV8 -#define STM32_PCLK (STM32_HCLK / 8) - -#elif STM32_PPRE == STM32_PPRE_DIV16 -#define STM32_PCLK (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE value specified" -#endif - -/* - * Compatibility definitions. - */ -#define STM32_PCLK1 STM32_PCLK -#define STM32_PCLK2 STM32_PCLK - -/* - * APB frequency check. - */ -#if STM32_PCLK > STM32_PCLK_MAX -#error "STM32_PCLK exceeding maximum frequency (STM32_PCLK_MAX)" -#endif - -/** - * @brief MCO divider clock frequency. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 - -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK -#define STM32_MCODIVCLK STM32_SYSCLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 -#define STM32_MCODIVCLK STM32_HSI16CLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_PLLRCLK -#define STM32_MCODIVCLK STM32_PLL_R_CLKOUT - -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK - -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock frequency. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV32 -#define STM32_MCOCLK (STM32_MCODIVCLK / 32) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV64 -#define STM32_MCOCLK (STM32_MCODIVCLK / 64) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV128 -#define STM32_MCOCLK (STM32_MCODIVCLK / 128) - -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief RTC clock frequency. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 clock frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_PCLK) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 -#define STM32_USART1CLK STM32_HSI16CLK -#elif STM32_USART1SEL == STM32_USART1SEL_LSE -#define STM32_USART1CLK STM32_LSECLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 clock frequency. - */ -#if (STM32_USART2SEL == STM32_USART2SEL_PCLK) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK -#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 -#define STM32_USART2CLK STM32_HSI16CLK -#elif STM32_USART2SEL == STM32_USART2SEL_LSE -#define STM32_USART2CLK STM32_LSECLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 frequency. - */ -#define STM32_USART3CLK STM32_PCLK - -/** - * @brief UART4 frequency. - */ -#define STM32_UART4CLK STM32_PCLK - -/** - * @brief UART5 frequency. - */ -#define STM32_UART5CLK STM32_PCLK - -/** - * @brief LPUART1 clock frequency. - */ -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK) || defined(__DOXYGEN__) -#define STM32_LPUART1CLK STM32_PCLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK -#define STM32_LPUART1CLK STM32_SYSCLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 -#define STM32_LPUART1CLK STM32_HSI16CLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE -#define STM32_LPUART1CLK STM32_LSECLK -#else -#error "invalid source selected for LPUART1 clock" -#endif - -/** - * @brief CEC clock frequency. - */ -#if (STM32_CECSEL == STM32_CECSEL_HSI16DIV) || defined(__DOXYGEN__) -#define STM32_CECCLK (STM32_HSI16CLK / 448) -#elif STM32_CECSEL == STM32_CECSEL_LSE -#define STM32_CECCLK STM32_LSECLK -#else -#error "invalid source selected for CEC clock" -#endif - -/** - * @brief I2C1 clock frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 -#define STM32_I2C1CLK STM32_HSI16CLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2S1 clock frequency. - */ -#if (STM32_I2S1SEL == STM32_I2S1SEL_SYSCLK) || defined(__DOXYGEN__) -#define STM32_I2S1CLK STM32_SYSCLK -#elif STM32_I2S1SEL == STM32_I2S1SEL_PLLPCLK -#define STM32_I2S1CLK STM32_PLL_P_CLKOUT -#elif STM32_I2S1SEL == STM32_I2S1SEL_HSI16 -#define STM32_I2S1CLK STM32_HSI16CLK -#elif STM32_I2S1SEL == STM32_I2S1SEL_CKIN -#define STM32_I2S1CLK 0 /* Unknown, would require a board value */ -#else -#error "invalid source selected for I2S1 clock" -#endif - -/** - * @brief LPTIM1 clock frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI -#define STM32_LPTIM1CLK STM32_LSICLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 -#define STM32_LPTIM1CLK STM32_HSI16CLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE -#define STM32_LPTIM1CLK STM32_LSECLK -#else -#error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief LPTIM2 clock frequency. - */ -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK) || defined(__DOXYGEN__) -#define STM32_LPTIM2CLK STM32_PCLK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI -#define STM32_LPTIM2CLK STM32_LSICLK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 -#define STM32_LPTIM2CLK STM32_HSI16CLK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE -#define STM32_LPTIM2CLK STM32_LSECLK -#else -#error "invalid source selected for LPTIM2 clock" -#endif - -/** - * @brief RNGDIV field. - */ -#if (STM32_RNGDIV_VALUE == 1) || defined(__DOXYGEN__) -#define STM32_RNGDIV (0U << 28U) -#elif STM32_RNGDIV_VALUE == 2 -#define STM32_RNGDIV (1U << 28U) -#elif STM32_RNGDIV_VALUE == 4 -#define STM32_RNGDIV (2U << 28U) -#elif STM32_RNGDIV_VALUE == 8 -#define STM32_RNGDIV (3U << 28U) -#else -#error "invalid STM32_RNGDIV_VALUE value specified" -#endif - -/** - * @brief RNG clock frequency. - */ -#if (STM32_RNGSEL == STM32_RNGSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RNGCLK 0 -#elif STM32_RNGSEL == STM32_RNGSEL_HSI16 -#define STM32_RNGCLK (STM32_HSI16CLK / STM32_RNGDIV_VALUE) -#elif STM32_RNGSEL == STM32_RNGSEL_SYSCLK -#define STM32_RNGCLK (STM32_SYSCLK / STM32_RNGDIV_VALUE) -#elif STM32_RNGSEL == STM32_RNGSEL_PLLQCLK -#define STM32_RNGCLK (STM32_PLL_Q_CLKOUT / STM32_RNGDIV_VALUE) -#else -#error "invalid source selected for RNG clock" -#endif - -/** - * @brief ADC clock frequency. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_SYSCLK) || defined(__DOXYGEN__) -#define STM32_ADCCLK STM32_SYSCLK -#elif STM32_ADCSEL == STM32_ADCSEL_PLLPCLK -#define STM32_ADCCLK STM32_PLL_P_CLKOUT -#elif STM32_ADCSEL == STM32_ADCSEL_HSI16 -#define STM32_ADCCLK STM32_HSI16CLK -#else -#error "invalid source selected for ADC clock" -#endif - -/** - * @brief TIMPCLK clock frequency. - */ -#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMPCLK (STM32_PCLK * 1) -#else -#define STM32_TIMPCLK (STM32_PCLK * 2) -#endif - -/** - * @brief TIM1 clock frequency. - */ -#if (STM32_TIM1SEL == STM32_TIM1SEL_TIMPCLK) || defined(__DOXYGEN__) -#define STM32_TIM1CLK STM32_TIMPCLK -#elif STM32_TIM1SEL == STM32_TIM1SEL_PLLQCLK -#define STM32_TIM1CLK STM32_PLL_Q_CLKOUT -#else -#error "invalid source selected for TIM1 clock" -#endif - -/** - * @brief TIM15 clock frequency. - */ -#if (STM32_TIM15SEL == STM32_TIM15SEL_TIMPCLK) || defined(__DOXYGEN__) -#define STM32_TIM15CLK STM32_TIMPCLK -#elif STM32_TIM15SEL == STM32_TIM15SEL_PLLQCLK -#define STM32_TIM15CLK STM32_PLL_Q_CLKOUT -#else -#error "invalid source selected for TIM15 clock" -#endif - -/** - * @brief Clock of timers connected to APB1. - */ -#define STM32_TIMCLK1 STM32_TIMPCLK - -/** - * @brief Clock of timers connected to APB2. - */ -#define STM32_TIMCLK2 STM32_TIMPCLK - -#if STM32_HAS_TIM1617_ERRATA -/* TIM16 and TIM17 require special handling and checks on some devices, see - the errata: "TIM16 and TIM17 are unduly clocked by SYSCLK".*/ -#define STM32_TIM16CLK hal_lld_get_clock_point(CLK_SYSCLK) -#define STM32_TIM17CLK hal_lld_get_clock_point(CLK_SYSCLK) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0 - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_0 - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_1 - -#else -#define STM32_FLASHBITS (FLASH_ACR_LATENCY_1 | FLASH_ACR_LATENCY_0) -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx/hal_lld.h + * @brief STM32G0xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32G070xx. + * - STM32G071xx, STM32G081xx. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32G070xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32G0 Entry-level Value Line" + +#elif defined(STM32G071xx) +#define PLATFORM_NAME "STM32G0 Entry-level" + +#elif defined(STM32G081xx) +#define PLATFORM_NAME "STM32G0 Entry-level with Crypto" + +#else +#error "STM32G0 device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32G0XX) || defined(__DOXYGEN__) +#define STM32G0XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSI16CLK 16000000U /**< 16MHz internal clock. */ +#define STM32_LSICLK 32000U /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR1 register bits definitions + * @{ + */ +#define STM32_VOS_MASK (3U << 9U) /**< Core voltage mask. */ +#define STM32_VOS_RANGE1 (1U << 9U) /**< Core voltage 1.2 Volts. */ +#define STM32_VOS_RANGE2 (2U << 9U) /**< Core voltage 1.0 Volts. */ +/** @} */ + +/** + * @name PWR_CR2 register bits definitions + * @{ + */ +#define STM32_PVDE_DISABLED (0U << 1U) /**< PVD enable bit off. */ +#define STM32_PVDE_ENABLED (1U << 1U) /**< PVD enable bit on. */ + +#define STM32_PVDFT_MASK (7U << 1U) /**< PVDFT bits mask. */ +#define STM32_PVDFT(n) ((n) << 1U) /**< PVDFT level. */ +#define STM32_PVDFT_LEV0 STM32_PVDFT(0U) /**< PVDFT level 0. */ +#define STM32_PVDFT_LEV1 STM32_PVDFT(1U) /**< PVDFT level 1. */ +#define STM32_PVDFT_LEV2 STM32_PVDFT(2U) /**< PVDFT level 2. */ +#define STM32_PVDFT_LEV3 STM32_PVDFT(3U) /**< PVDFT level 3. */ +#define STM32_PVDFT_LEV4 STM32_PVDFT(4U) /**< PVDFT level 4. */ +#define STM32_PVDFT_LEV5 STM32_PVDFT(5U) /**< PVDFT level 5. */ +#define STM32_PVDFT_LEV6 STM32_PVDFT(6U) /**< PVDFT level 6. */ +#define STM32_PVDFT_LEV7 STM32_PVDFT(7U) /**< PVDFT level 7. */ + +#define STM32_PVDRT_MASK (7U << 4U) /**< PVDRT bits mask. */ +#define STM32_PVDRT(n) ((n) << 4U) /**< PVDRT level. */ +#define STM32_PVDRT_LEV0 STM32_PVDRT(0U) /**< PVDRT level 0. */ +#define STM32_PVDRT_LEV1 STM32_PVDRT(1U) /**< PVDRT level 1. */ +#define STM32_PVDRT_LEV2 STM32_PVDRT(2U) /**< PVDRT level 2. */ +#define STM32_PVDRT_LEV3 STM32_PVDRT(3U) /**< PVDRT level 3. */ +#define STM32_PVDRT_LEV4 STM32_PVDRT(4U) /**< PVDRT level 4. */ +#define STM32_PVDRT_LEV5 STM32_PVDRT(5U) /**< PVDRT level 5. */ +#define STM32_PVDRT_LEV6 STM32_PVDRT(6U) /**< PVDRT level 6. */ +#define STM32_PVDRT_LEV7 STM32_PVDRT(7U) /**< PVDRT level 7. */ +/** @} */ + +/** + * @name RCC_CR register bits definitions + * @{ + */ +#define STM32_HSIDIV_MASK (7U << 11U) /**< HSIDIV field mask. */ +#define STM32_HSIDIV_FIELD(n) ((n) << 11U) /**< HSIDIV field value. */ +#define STM32_HSIDIV_1 STM32_HSIDIV_FIELD(0U) +#define STM32_HSIDIV_2 STM32_HSIDIV_FIELD(1U) +#define STM32_HSIDIV_4 STM32_HSIDIV_FIELD(2U) +#define STM32_HSIDIV_8 STM32_HSIDIV_FIELD(3U) +#define STM32_HSIDIV_16 STM32_HSIDIV_FIELD(4U) +#define STM32_HSIDIV_32 STM32_HSIDIV_FIELD(5U) +#define STM32_HSIDIV_64 STM32_HSIDIV_FIELD(6U) +#define STM32_HSIDIV_128 STM32_HSIDIV_FIELD(7U) +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (7U << 0U) /**< SW field mask. */ +#define STM32_SW_HSISYS (0U << 0U) /**< SYSCLK source is HSISYS. */ +#define STM32_SW_HSE (1U << 0U) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLLRCLK (2U << 0U) /**< SYSCLK source is PLL. */ +#define STM32_SW_LSI (3U << 0U) /**< SYSCLK source is LSI. */ +#define STM32_SW_LSE (4U << 0U) /**< SYSCLK source is LSE. */ + +#define STM32_HPRE_MASK (15U << 8U) /**< HPRE field mask. */ +#define STM32_HPRE_FIELD(n) ((n) << 8U) /**< HPRE field value. */ +#define STM32_HPRE_DIV1 STM32_HPRE_FIELD(0U) +#define STM32_HPRE_DIV2 STM32_HPRE_FIELD(8U) +#define STM32_HPRE_DIV4 STM32_HPRE_FIELD(9U) +#define STM32_HPRE_DIV8 STM32_HPRE_FIELD(10U) +#define STM32_HPRE_DIV16 STM32_HPRE_FIELD(11U) +#define STM32_HPRE_DIV64 STM32_HPRE_FIELD(12U) +#define STM32_HPRE_DIV128 STM32_HPRE_FIELD(13U) +#define STM32_HPRE_DIV256 STM32_HPRE_FIELD(14U) +#define STM32_HPRE_DIV512 STM32_HPRE_FIELD(15U) + +#define STM32_PPRE_MASK (7U << 12U) /**< PPRE field mask. */ +#define STM32_PPRE_FIELD(n) ((n) << 12U) /**< PPRE field value. */ +#define STM32_PPRE_DIV1 STM32_PPRE_FIELD(0U) +#define STM32_PPRE_DIV2 STM32_PPRE_FIELD(4U) +#define STM32_PPRE_DIV4 STM32_PPRE_FIELD(5U) +#define STM32_PPRE_DIV8 STM32_PPRE_FIELD(6U) +#define STM32_PPRE_DIV16 STM32_PPRE_FIELD(7U) + +#define STM32_MCOSEL_MASK (7U << 24U) /**< MCOSEL field mask. */ +#define STM32_MCOSEL_NOCLOCK (0U << 24U) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1U << 24U) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI16 (3U << 24U) /**< HSI16 clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4U << 24U) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLRCLK (5U << 24U) /**< PLLR clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6U << 24U) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7U << 24U) /**< LSE clock on MCO pin. */ + +#define STM32_MCOPRE_MASK (7U << 28U) /**< MCOPRE field mask. */ +#define STM32_MCOPRE_FIELD(n) ((n) << 28U)/**< MCOPRE field value */ +#define STM32_MCOPRE_DIV1 STM32_MCOPRE_FIELD(0U) +#define STM32_MCOPRE_DIV2 STM32_MCOPRE_FIELD(1U) +#define STM32_MCOPRE_DIV4 STM32_MCOPRE_FIELD(2U) +#define STM32_MCOPRE_DIV8 STM32_MCOPRE_FIELD(3U) +#define STM32_MCOPRE_DIV16 STM32_MCOPRE_FIELD(4U) +#define STM32_MCOPRE_DIV32 STM32_MCOPRE_FIELD(5U) +#define STM32_MCOPRE_DIV64 STM32_MCOPRE_FIELD(6U) +#define STM32_MCOPRE_DIV128 STM32_MCOPRE_FIELD(7U) +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CCIPR register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3U << 0U) /**< USART1SEL mask. */ +#define STM32_USART1SEL_PCLK (0U << 0U) /**< USART1 source is PCLK. */ +#define STM32_USART1SEL_SYSCLK (1U << 0U) /**< USART1 source is SYSCLK. */ +#define STM32_USART1SEL_HSI16 (2U << 0U) /**< USART1 source is HSI16. */ +#define STM32_USART1SEL_LSE (3U << 0U) /**< USART1 source is LSE. */ + +#define STM32_USART2SEL_MASK (3U << 2U) /**< USART2 mask. */ +#define STM32_USART2SEL_PCLK (0U << 2U) /**< USART2 source is PCLK. */ +#define STM32_USART2SEL_SYSCLK (1U << 2U) /**< USART2 source is SYSCLK. */ +#define STM32_USART2SEL_HSI16 (2U << 2U) /**< USART2 source is HSI16. */ +#define STM32_USART2SEL_LSE (3U << 2U) /**< USART2 source is LSE. */ + +#define STM32_CECSEL_MASK (1U << 6U) /**< CEC mask. */ +#define STM32_CECSEL_HSI16DIV (0U << 6U) /**< CEC source is HSI16/448. */ +#define STM32_CECSEL_LSE (1U << 6U) /**< CEC source is LSE. */ + +#define STM32_LPUART1SEL_MASK (3U << 10U) /**< LPUART1 mask. */ +#define STM32_LPUART1SEL_PCLK (0U << 10U) /**< LPUART1 source is PCLK. */ +#define STM32_LPUART1SEL_SYSCLK (1U << 10U) /**< LPUART1 source is SYSCLK. */ +#define STM32_LPUART1SEL_HSI16 (2U << 10U) /**< LPUART1 source is HSI16. */ +#define STM32_LPUART1SEL_LSE (3U << 10U) /**< LPUART1 source is LSE. */ + +#define STM32_I2C1SEL_MASK (3U << 12U) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK (0U << 12U) /**< I2C1 source is PCLK. */ +#define STM32_I2C1SEL_SYSCLK (1U << 12U) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI16 (2U << 12U) /**< I2C1 source is HSI16. */ + +#define STM32_I2S1SEL_MASK (3U << 14U) /**< I2S1SEL mask. */ +#define STM32_I2S1SEL_SYSCLK (0U << 14U) /**< I2S1 source is SYSCLK. */ +#define STM32_I2S1SEL_PLLPCLK (1U << 14U) /**< I2S1 source is PLLPCLK. */ +#define STM32_I2S1SEL_HSI16 (2U << 14U) /**< I2S1 source is HSI16. */ +#define STM32_I2S1SEL_CKIN (3U << 14U) /**< I2S1 source is CKIN. */ + +#define STM32_LPTIM1SEL_MASK (3U << 18U) /**< LPTIM1SEL mask. */ +#define STM32_LPTIM1SEL_PCLK (0U << 18U) /**< LPTIM1 source is PCLK. */ +#define STM32_LPTIM1SEL_LSI (1U << 18U) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_HSI16 (2U << 18U) /**< LPTIM1 source is HSI16. */ +#define STM32_LPTIM1SEL_LSE (3U << 18U) /**< LPTIM1 source is LSE. */ + +#define STM32_LPTIM2SEL_MASK (3U << 20U) /**< LPTIM2SEL mask. */ +#define STM32_LPTIM2SEL_PCLK (0U << 20U) /**< LPTIM2 source is PCLK. */ +#define STM32_LPTIM2SEL_LSI (1U << 20U) /**< LPTIM2 source is LSI. */ +#define STM32_LPTIM2SEL_HSI16 (2U << 20U) /**< LPTIM2 source is HSI16. */ +#define STM32_LPTIM2SEL_LSE (3U << 20U) /**< LPTIM2 source is LSE. */ + +#define STM32_TIM1SEL_MASK (1U << 22U) /**< TIM1SEL mask. */ +#define STM32_TIM1SEL_TIMPCLK (0U << 22U) /**< TIM1SEL source is TIMPCLK. */ +#define STM32_TIM1SEL_PLLQCLK (1U << 22U) /**< TIM1SEL source is PLLQCLK. */ + +#define STM32_TIM15SEL_MASK (1U << 24U) /**< TIM15SEL mask. */ +#define STM32_TIM15SEL_TIMPCLK (0U << 24U) /**< TIM15SEL source is TIMPCLK.*/ +#define STM32_TIM15SEL_PLLQCLK (1U << 24U) /**< TIM15SEL source is PLLQCLK.*/ + +#define STM32_RNGSEL_MASK (3U << 26U) /**< RNGSEL mask. */ +#define STM32_RNGSEL_NOCLOCK (0U << 26U) /**< RNG source is disabled. */ +#define STM32_RNGSEL_HSI16 (1U << 26U) /**< RNG source is HSI16. */ +#define STM32_RNGSEL_SYSCLK (2U << 26U) /**< RNG source is SYSCLK. */ +#define STM32_RNGSEL_PLLQCLK (3U << 26U) /**< RNG source is PLLQCLK. */ + +#define STM32_RNGDIV_MASK (3U << 28U) /**< RNGDIV field mask. */ +#define STM32_RNGDIV_FIELD(n) ((n) << 28U)/**< RNGDIV field value */ +#define STM32_RNGDIV_1 STM32_RNGDIV_FIELD(0U) +#define STM32_RNGDIV_2 STM32_RNGDIV_FIELD(1U) +#define STM32_RNGDIV_4 STM32_RNGDIV_FIELD(2U) +#define STM32_RNGDIV_8 STM32_RNGDIV_FIELD(3U) + +#define STM32_ADCSEL_MASK (3U << 30U) /**< ADCSEL mask. */ +#define STM32_ADCSEL_SYSCLK (0U << 30U) /**< ADC source is SYSCLK. */ +#define STM32_ADCSEL_PLLPCLK (1U << 30U) /**< ADC source is PLLPCLK. */ +#define STM32_ADCSEL_HSI16 (2U << 30U) /**< ADC source is HSI16. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3U << 8U) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0U << 8U) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1U << 8U) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2U << 8U) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3U << 8U) /**< RTC source is HSE divided. */ + +#define STM32_LSCOSEL_MASK (3U << 24U) /**< LSCO pin clock source. */ +#define STM32_LSCOSEL_NOCLOCK (0U << 24U) /**< No clock on LSCO pin. */ +#define STM32_LSCOSEL_LSI (1U << 24U) /**< LSI on LSCO pin. */ +#define STM32_LSCOSEL_LSE (3U << 24U) /**< LSE on LSCO pin. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_RANGE1 +#endif + +/** + * @brief PWR CR2 register initialization value. + */ +#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) +#define STM32_PWR_CR2 (STM32_PVDRT_LEV0 | \ + STM32_PVDFT_LEV0 | \ + STM32_PVDE_DISABLED) +#endif + +/** + * @brief HSI16 divider value. + * @note The allowed values are 1, 2, 4, 8, 16, 32, 64, 128. + */ +#if !defined(STM32_HSIDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_HSIDIV_VALUE 1 +#endif + +/** + * @brief Enables or disables the HSI16 clock source. + */ +#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 64MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLLRCLK +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 64MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 1..8. + * @note The default value is calculated for a 64MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 2 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 8..86. + * @note The default value is calculated for a 64MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 16 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2..32. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 2 +#endif + +/** + * @brief PLLQ divider value. + * @note The allowed values are 2..8. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 4 +#endif + +/** + * @brief PLLR divider value. + * @note The allowed values are 2..8. + * @note The default value is calculated for a 64MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLR_VALUE 2 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 64MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB prescaler value. + */ +#if !defined(STM32_PPRE) || defined(__DOXYGEN__) +#define STM32_PPRE STM32_PPRE_DIV1 +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief LSCO clock source. + */ +#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#endif + +/** + * @brief LPUART1 clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#endif + +/** + * @brief CEC clock source. + */ +#if !defined(STM32_CECSEL) || defined(__DOXYGEN__) +#define STM32_CECSEL STM32_CECSEL_HSI16DIV +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK +#endif + +/** + * @brief I2S1 clock source. + */ +#if !defined(STM32_I2S1SEL) || defined(__DOXYGEN__) +#define STM32_I2S1SEL STM32_I2S1SEL_SYSCLK +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK +#endif + +/** + * @brief LPTIM2 clock source. + */ +#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK +#endif + +/** + * @brief TIM1 clock source. + */ +#if !defined(STM32_TIM1SEL) || defined(__DOXYGEN__) +#define STM32_TIM1SEL STM32_TIM1SEL_TIMPCLK +#endif + +/** + * @brief TIM15 clock source. + */ +#if !defined(STM32_TIM15SEL) || defined(__DOXYGEN__) +#define STM32_TIM15SEL STM32_TIM15SEL_TIMPCLK +#endif + +/** + * @brief RNG clock source. + */ +#if !defined(STM32_RNGSEL) || defined(__DOXYGEN__) +#define STM32_RNGSEL STM32_RNGSEL_HSI16 +#endif + +/** + * @brief RNG divider value. + */ +#if !defined(STM32_RNGDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_RNGDIV_VALUE 1 +#endif + +/** + * @brief ADC clock source. + */ +#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) +#define STM32_ADCSEL STM32_ADCSEL_PLLPCLK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32G0xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G0xx_MCUCONF not defined" +#endif + +#if defined(STM32G070xx) && !defined(STM32G070_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G070_MCUCONF not defined" + +#elif defined(STM32G071xx) && !defined(STM32G071_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G071_MCUCONF not defined" + +#elif defined(STM32G081xx) && !defined(STM32G081_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G071_MCUCONF not defined" + +#endif + +/* + * Board files sanity checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif + +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) +/** + * @name System Limits + * @{ + */ +/** + * @brief Maximum SYSCLK clock frequency. + */ +#define STM32_SYSCLK_MAX 64000000 + +/** + * @brief Maximum HSE clock frequency at current voltage setting. + */ +#define STM32_HSECLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 48000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MIN 8000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 16000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 2660000 + +/** + * @brief Maximum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MAX 344000000 + +/** + * @brief Minimum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MIN 64000000 + +/** + * @brief Maximum PLL-P output clock frequency. + */ +#define STM32_PLLP_MAX 128000000 + +/** + * @brief Minimum PLL-P output clock frequency. + */ +#define STM32_PLLP_MIN 3090000 + +/** + * @brief Maximum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MAX 128000000 + +/** + * @brief Minimum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MIN 12000000 + +/** + * @brief Maximum PLL-R output clock frequency. + */ +#define STM32_PLLR_MAX 64000000 + +/** + * @brief Minimum PLL-R output clock frequency. + */ +#define STM32_PLLR_MIN 12000000 + +/** + * @brief Maximum APB clock frequency. + */ +#define STM32_PCLK_MAX 64000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 350000000 +/** @} */ + +/** + * @name Flash Wait states + * @{ + */ +#define STM32_0WS_THRESHOLD 24000000 +#define STM32_1WS_THRESHOLD 48000000 +#define STM32_2WS_THRESHOLD 64000000 +#define STM32_3WS_THRESHOLD 0 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +/** @} */ + +#elif STM32_VOS == STM32_VOS_RANGE2 +#define STM32_SYSCLK_MAX 16000000 +#define STM32_HSECLK_MAX 16000000 +#define STM32_HSECLK_BYP_MAX 16000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 8000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_LSECLK_BYP_MIN 32768 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MIN 2660000 +#define STM32_PLLVCO_MAX 128000000 +#define STM32_PLLVCO_MIN 96000000 +#define STM32_PLLP_MAX 40000000 +#define STM32_PLLP_MIN 3090000 +#define STM32_PLLQ_MAX 32000000 +#define STM32_PLLQ_MIN 12000000 +#define STM32_PLLR_MAX 16000000 +#define STM32_PLLR_MIN 12000000 +#define STM32_PCLK_MAX 16000000 +#define STM32_ADCCLK_MAX 16000000 + +#define STM32_0WS_THRESHOLD 8000000 +#define STM32_1WS_THRESHOLD 16000000 +#define STM32_2WS_THRESHOLD 0 +#define STM32_3WS_THRESHOLD 0 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 + +#else +#error "invalid STM32_VOS value specified" +#endif + +/* + * HSI16 related checks. + */ +#if STM32_HSI16_ENABLED +#else /* !STM32_HSI16_ENABLED */ + +#if STM32_SW == STM32_SW_HSISYS +#error "HSI16 not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +/* NOTE: Missing checks on the HSI16 pre-muxes, it is also required for newer + L4 devices.*/ + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16)) +#error "HSI16 not enabled, required by STM32_MCOSEL" +#endif + +#if (STM32_USART1SEL == STM32_USART1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART1SEL" +#endif +#if (STM32_USART2SEL == STM32_USART2SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART2SEL" +#endif +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_LPUART1SEL" +#endif + +#if (STM32_CECSEL == STM32_CECSEL_HSI16DIV) +#error "HSI16 not enabled, required by STM32_CECSEL" +#endif + +#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_I2C1SEL" +#endif +#if (STM32_I2S1SEL == STM32_I2S1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_I2S1SEL" +#endif + +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_LPTIM1SEL" +#endif +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) +#error "HSI16 not enabled, required by STM32_LPTIM2SEL" +#endif + +#if (STM32_RNGSEL == STM32_RNGSEL_HSI16) +#error "HSI16 not enabled, required by STM32_RNGSEL" +#endif + +#if (STM32_ADCSEL == STM32_ADCSEL_HSI16) +#error "HSI16 not enabled, required by STM32_ADCSEL" +#endif + +#endif /* !STM32_HSI16_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + + #if STM32_HSECLK == 0 + #error "HSE frequency not defined" + #else /* STM32_HSECLK != 0 */ + #if defined(STM32_HSE_BYPASS) + #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" + #endif + #else /* !defined(STM32_HSE_BYPASS) */ + #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" + #endif + #endif /* !defined(STM32_HSE_BYPASS) */ + #endif /* STM32_HSECLK != 0 */ + + #else /* !STM32_HSE_ENABLED */ + + #if STM32_SW == STM32_SW_HSE + #error "HSE not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) + #error "HSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV + #error "HSE not enabled, required by STM32_RTCSEL" + #endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + + #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) + #error "LSI not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSI + #error "LSI not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSI + #error "LSI not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + + #if (STM32_LSECLK == 0) + #error "LSE frequency not defined" + #endif + + #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) + #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" + #endif + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) + #error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" + #endif + +#else /* !STM32_LSE_ENABLED */ + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) + #error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_LSE + #error "LSE not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSE + #error "LSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSE + #error "LSE not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief STM32_HSIDIV field. + */ +#if (STM32_HSIDIV_VALUE == 1) || defined(__DOXYGEN__) +#define STM32_HSIDIV STM32_HSIDIV_1 +#elif STM32_HSIDIV_VALUE == 2 +#define STM32_HSIDIV STM32_HSIDIV_2 +#elif STM32_HSIDIV_VALUE == 4 +#define STM32_HSIDIV STM32_HSIDIV_4 +#elif STM32_HSIDIV_VALUE == 8 +#define STM32_HSIDIV STM32_HSIDIV_8 +#elif STM32_HSIDIV_VALUE == 16 +#define STM32_HSIDIV STM32_HSIDIV_16 +#elif STM32_HSIDIV_VALUE == 32 +#define STM32_HSIDIV STM32_HSIDIV_32 +#elif STM32_HSIDIV_VALUE == 64 +#define STM32_HSIDIV STM32_HSIDIV_64 +#elif STM32_HSIDIV_VALUE == 128 +#define STM32_HSIDIV STM32_HSIDIV_128 +#else +#error "invalid STM32_HSIDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 8)) || \ + defined(__DOXYGEN__) +#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) +#else +#error "invalid STM32_PLLM_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 +#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK +#define STM32_PLLCLKIN 0 + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLL input frequency range check. + */ +#if (STM32_PLLCLKIN != 0) && \ + ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_SW == STM32_SW_PLLRCLK) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ + (STM32_TIM1SEL == STM32_TIM1SEL_PLLQCLK) || \ + (STM32_TIM15SEL == STM32_TIM15SEL_PLLQCLK) || \ + (STM32_RNGSEL == STM32_RNGSEL_PLLQCLK) || \ + (STM32_ADCSEL == STM32_ADCSEL_PLLPCLK) || \ + (STM32_I2S1SEL == STM32_I2S1SEL_PLLPCLK) || \ + defined(__DOXYGEN__) + +#if STM32_PLLCLKIN == 0 +#error "PLL activation required but no PLL clock selected" +#endif + +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 86)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 8) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLR field. + */ +#if ((STM32_PLLR_VALUE >= 2) && (STM32_PLLR_VALUE <= 8)) || \ + defined(__DOXYGEN__) +#define STM32_PLLR ((STM32_PLLR_VALUE - 1) << 29) +#else +#error "invalid STM32_PLLR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 8)) || \ + defined(__DOXYGEN__) +#define STM32_PLLQ ((STM32_PLLQ_VALUE - 1) << 25) +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if ((STM32_PLLP_VALUE >= 2) && (STM32_PLLP_VALUE <= 32)) || \ + defined(__DOXYGEN__) +#define STM32_PLLP ((STM32_PLLP_VALUE - 1) << 17) +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLREN field. + */ +#if (STM32_SW == STM32_SW_PLLRCLK) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ + defined(__DOXYGEN__) +#define STM32_PLLREN (1 << 28) +#else +#define STM32_PLLREN (0 << 28) +#endif + +/** + * @brief STM32_PLLQEN field. + */ +#if (STM32_TIM1SEL == STM32_TIM1SEL_PLLQCLK) || \ + (STM32_TIM15SEL == STM32_TIM15SEL_PLLQCLK) || \ + (STM32_RNGSEL == STM32_RNGSEL_PLLQCLK) || \ + defined(__DOXYGEN__) +#define STM32_PLLQEN (1 << 24) +#else +#define STM32_PLLQEN (0 << 24) +#endif + +/** + * @brief STM32_PLLPEN field. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_PLLPCLK) || \ + (STM32_I2S1SEL == STM32_I2S1SEL_PLLPCLK) || \ + defined(__DOXYGEN__) +#define STM32_PLLPEN (1 << 16) +#else +#define STM32_PLLPEN (0 << 16) +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL R output clock frequency. + */ +#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) + +/** + * @brief PLL Q output clock frequency. + */ +#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) + +/** + * @brief PLL P output clock frequency. + */ +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) + +/* + * PLL-R output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/* + * PLL-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLL-P output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/** + * @brief HSISYS clock frequency. + */ +#define STM32_HSISYSCLK (STM32_HSI16CLK / STM32_HSIDIV_VALUE) + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_HSISYSCLK + +#elif (STM32_SW == STM32_SW_HSISYS) +#define STM32_SYSCLK STM32_HSISYSCLK + +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK + +#elif (STM32_SW == STM32_SW_PLLRCLK) +#define STM32_SYSCLK STM32_PLL_R_CLKOUT + +#elif (STM32_SW == STM32_SW_LSI) +#define STM32_SYSCLK STM32_LSICLK + +#elif (STM32_SW == STM32_SW_LSE) +#define STM32_SYSCLK STM32_LSECLK + +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) + +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) + +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) + +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) + +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) + +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) + +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) + +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) + +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) + +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB frequency. + */ +#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK (STM32_HCLK / 1) + +#elif STM32_PPRE == STM32_PPRE_DIV2 +#define STM32_PCLK (STM32_HCLK / 2) + +#elif STM32_PPRE == STM32_PPRE_DIV4 +#define STM32_PCLK (STM32_HCLK / 4) + +#elif STM32_PPRE == STM32_PPRE_DIV8 +#define STM32_PCLK (STM32_HCLK / 8) + +#elif STM32_PPRE == STM32_PPRE_DIV16 +#define STM32_PCLK (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE value specified" +#endif + +/* + * Compatibility definitions. + */ +#define STM32_PCLK1 STM32_PCLK +#define STM32_PCLK2 STM32_PCLK + +/* + * APB frequency check. + */ +#if STM32_PCLK > STM32_PCLK_MAX +#error "STM32_PCLK exceeding maximum frequency (STM32_PCLK_MAX)" +#endif + +/** + * @brief MCO divider clock frequency. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 + +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK +#define STM32_MCODIVCLK STM32_SYSCLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 +#define STM32_MCODIVCLK STM32_HSI16CLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_PLLRCLK +#define STM32_MCODIVCLK STM32_PLL_R_CLKOUT + +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK + +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock frequency. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV32 +#define STM32_MCOCLK (STM32_MCODIVCLK / 32) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV64 +#define STM32_MCOCLK (STM32_MCODIVCLK / 64) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV128 +#define STM32_MCOCLK (STM32_MCODIVCLK / 128) + +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief RTC clock frequency. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 clock frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_PCLK) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 +#define STM32_USART1CLK STM32_HSI16CLK +#elif STM32_USART1SEL == STM32_USART1SEL_LSE +#define STM32_USART1CLK STM32_LSECLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 clock frequency. + */ +#if (STM32_USART2SEL == STM32_USART2SEL_PCLK) || defined(__DOXYGEN__) +#define STM32_USART2CLK STM32_PCLK +#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 +#define STM32_USART2CLK STM32_HSI16CLK +#elif STM32_USART2SEL == STM32_USART2SEL_LSE +#define STM32_USART2CLK STM32_LSECLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 frequency. + */ +#define STM32_USART3CLK STM32_PCLK + +/** + * @brief UART4 frequency. + */ +#define STM32_UART4CLK STM32_PCLK + +/** + * @brief UART5 frequency. + */ +#define STM32_UART5CLK STM32_PCLK + +/** + * @brief LPUART1 clock frequency. + */ +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK) || defined(__DOXYGEN__) +#define STM32_LPUART1CLK STM32_PCLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK +#define STM32_LPUART1CLK STM32_SYSCLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 +#define STM32_LPUART1CLK STM32_HSI16CLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE +#define STM32_LPUART1CLK STM32_LSECLK +#else +#error "invalid source selected for LPUART1 clock" +#endif + +/** + * @brief CEC clock frequency. + */ +#if (STM32_CECSEL == STM32_CECSEL_HSI16DIV) || defined(__DOXYGEN__) +#define STM32_CECCLK (STM32_HSI16CLK / 448) +#elif STM32_CECSEL == STM32_CECSEL_LSE +#define STM32_CECCLK STM32_LSECLK +#else +#error "invalid source selected for CEC clock" +#endif + +/** + * @brief I2C1 clock frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_PCLK +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 +#define STM32_I2C1CLK STM32_HSI16CLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2S1 clock frequency. + */ +#if (STM32_I2S1SEL == STM32_I2S1SEL_SYSCLK) || defined(__DOXYGEN__) +#define STM32_I2S1CLK STM32_SYSCLK +#elif STM32_I2S1SEL == STM32_I2S1SEL_PLLPCLK +#define STM32_I2S1CLK STM32_PLL_P_CLKOUT +#elif STM32_I2S1SEL == STM32_I2S1SEL_HSI16 +#define STM32_I2S1CLK STM32_HSI16CLK +#elif STM32_I2S1SEL == STM32_I2S1SEL_CKIN +#define STM32_I2S1CLK 0 /* Unknown, would require a board value */ +#else +#error "invalid source selected for I2S1 clock" +#endif + +/** + * @brief LPTIM1 clock frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK) || defined(__DOXYGEN__) +#define STM32_LPTIM1CLK STM32_PCLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI +#define STM32_LPTIM1CLK STM32_LSICLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 +#define STM32_LPTIM1CLK STM32_HSI16CLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE +#define STM32_LPTIM1CLK STM32_LSECLK +#else +#error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief LPTIM2 clock frequency. + */ +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK) || defined(__DOXYGEN__) +#define STM32_LPTIM2CLK STM32_PCLK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI +#define STM32_LPTIM2CLK STM32_LSICLK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 +#define STM32_LPTIM2CLK STM32_HSI16CLK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE +#define STM32_LPTIM2CLK STM32_LSECLK +#else +#error "invalid source selected for LPTIM2 clock" +#endif + +/** + * @brief RNGDIV field. + */ +#if (STM32_RNGDIV_VALUE == 1) || defined(__DOXYGEN__) +#define STM32_RNGDIV (0U << 28U) +#elif STM32_RNGDIV_VALUE == 2 +#define STM32_RNGDIV (1U << 28U) +#elif STM32_RNGDIV_VALUE == 4 +#define STM32_RNGDIV (2U << 28U) +#elif STM32_RNGDIV_VALUE == 8 +#define STM32_RNGDIV (3U << 28U) +#else +#error "invalid STM32_RNGDIV_VALUE value specified" +#endif + +/** + * @brief RNG clock frequency. + */ +#if (STM32_RNGSEL == STM32_RNGSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RNGCLK 0 +#elif STM32_RNGSEL == STM32_RNGSEL_HSI16 +#define STM32_RNGCLK (STM32_HSI16CLK / STM32_RNGDIV_VALUE) +#elif STM32_RNGSEL == STM32_RNGSEL_SYSCLK +#define STM32_RNGCLK (STM32_SYSCLK / STM32_RNGDIV_VALUE) +#elif STM32_RNGSEL == STM32_RNGSEL_PLLQCLK +#define STM32_RNGCLK (STM32_PLL_Q_CLKOUT / STM32_RNGDIV_VALUE) +#else +#error "invalid source selected for RNG clock" +#endif + +/** + * @brief ADC clock frequency. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_SYSCLK) || defined(__DOXYGEN__) +#define STM32_ADCCLK STM32_SYSCLK +#elif STM32_ADCSEL == STM32_ADCSEL_PLLPCLK +#define STM32_ADCCLK STM32_PLL_P_CLKOUT +#elif STM32_ADCSEL == STM32_ADCSEL_HSI16 +#define STM32_ADCCLK STM32_HSI16CLK +#else +#error "invalid source selected for ADC clock" +#endif + +/** + * @brief TIMPCLK clock frequency. + */ +#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMPCLK (STM32_PCLK * 1) +#else +#define STM32_TIMPCLK (STM32_PCLK * 2) +#endif + +/** + * @brief TIM1 clock frequency. + */ +#if (STM32_TIM1SEL == STM32_TIM1SEL_TIMPCLK) || defined(__DOXYGEN__) +#define STM32_TIM1CLK STM32_TIMPCLK +#elif STM32_TIM1SEL == STM32_TIM1SEL_PLLQCLK +#define STM32_TIM1CLK STM32_PLL_Q_CLKOUT +#else +#error "invalid source selected for TIM1 clock" +#endif + +/** + * @brief TIM15 clock frequency. + */ +#if (STM32_TIM15SEL == STM32_TIM15SEL_TIMPCLK) || defined(__DOXYGEN__) +#define STM32_TIM15CLK STM32_TIMPCLK +#elif STM32_TIM15SEL == STM32_TIM15SEL_PLLQCLK +#define STM32_TIM15CLK STM32_PLL_Q_CLKOUT +#else +#error "invalid source selected for TIM15 clock" +#endif + +/** + * @brief Clock of timers connected to APB1. + */ +#define STM32_TIMCLK1 STM32_TIMPCLK + +/** + * @brief Clock of timers connected to APB2. + */ +#define STM32_TIMCLK2 STM32_TIMPCLK + +#if STM32_HAS_TIM1617_ERRATA +/* TIM16 and TIM17 require special handling and checks on some devices, see + the errata: "TIM16 and TIM17 are unduly clocked by SYSCLK".*/ +#define STM32_TIM16CLK hal_lld_get_clock_point(CLK_SYSCLK) +#define STM32_TIM17CLK hal_lld_get_clock_point(CLK_SYSCLK) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0 + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_0 + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_1 + +#else +#define STM32_FLASHBITS (FLASH_ACR_LATENCY_1 | FLASH_ACR_LATENCY_0) +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/platform.mk b/os/hal/ports/STM32/STM32G0xx/platform.mk index a40f7cc7f2..4cab52f18c 100644 --- a/os/hal/ports/STM32/STM32G0xx/platform.mk +++ b/os/hal/ports/STM32/STM32G0xx/platform.mk @@ -1,44 +1,44 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/hal_lld.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/hal_lld.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/hal_efl_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32G0xx/stm32_dmamux.h b/os/hal/ports/STM32/STM32G0xx/stm32_dmamux.h index 38226919f6..8cef754e23 100644 --- a/os/hal/ports/STM32/STM32G0xx/stm32_dmamux.h +++ b/os/hal/ports/STM32/STM32G0xx/stm32_dmamux.h @@ -1,131 +1,131 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx/stm32_dmamux.h - * @brief STM32G0xx DMAMUX handler header. - * - * @addtogroup STM32G0xx_DMAMUX - * @{ - */ - -#ifndef STM32_DMAMUX_H -#define STM32_DMAMUX_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name DMAMUX1 request sources - * @{ - */ -#define STM32_DMAMUX1_REQ_GEN0 1 -#define STM32_DMAMUX1_REQ_GEN1 2 -#define STM32_DMAMUX1_REQ_GEN2 3 -#define STM32_DMAMUX1_REQ_GEN3 4 -#define STM32_DMAMUX1_ADC1 5 -#define STM32_DMAMUX1_AES_IN 6 -#define STM32_DMAMUX1_AES_OUT 7 -#define STM32_DMAMUX1_DAC1_CH1 8 -#define STM32_DMAMUX1_DAC1_CH2 9 -#define STM32_DMAMUX1_I2C1_RX 10 -#define STM32_DMAMUX1_I2C1_TX 11 -#define STM32_DMAMUX1_I2C2_RX 12 -#define STM32_DMAMUX1_I2C2_TX 13 -#define STM32_DMAMUX1_LPUART1_RX 14 -#define STM32_DMAMUX1_LPUART1_TX 15 -#define STM32_DMAMUX1_SPI1_RX 16 -#define STM32_DMAMUX1_SPI1_TX 17 -#define STM32_DMAMUX1_SPI2_RX 18 -#define STM32_DMAMUX1_SPI2_TX 19 -#define STM32_DMAMUX1_TIM1_CH1 20 -#define STM32_DMAMUX1_TIM1_CH2 21 -#define STM32_DMAMUX1_TIM1_CH3 22 -#define STM32_DMAMUX1_TIM1_CH4 23 -#define STM32_DMAMUX1_TIM1_COM 24 -#define STM32_DMAMUX1_TIM1_UP 25 -#define STM32_DMAMUX1_TIM2_CH1 26 -#define STM32_DMAMUX1_TIM2_CH2 27 -#define STM32_DMAMUX1_TIM2_CH3 28 -#define STM32_DMAMUX1_TIM2_CH4 29 -#define STM32_DMAMUX1_TIM2_TRIG 30 -#define STM32_DMAMUX1_TIM2_UP 31 -#define STM32_DMAMUX1_TIM3_CH1 32 -#define STM32_DMAMUX1_TIM3_CH2 33 -#define STM32_DMAMUX1_TIM3_CH3 34 -#define STM32_DMAMUX1_TIM3_CH4 35 -#define STM32_DMAMUX1_TIM3_TRIG 36 -#define STM32_DMAMUX1_TIM3_UP 37 -#define STM32_DMAMUX1_TIM6_UP 38 -#define STM32_DMAMUX1_TIM7_UP 39 -#define STM32_DMAMUX1_TIM15_CH1 40 -#define STM32_DMAMUX1_TIM15_CH2 41 -#define STM32_DMAMUX1_TIM15_COM 42 -#define STM32_DMAMUX1_TIM15_UP 43 -#define STM32_DMAMUX1_TIM16_CH1 44 -#define STM32_DMAMUX1_TIM16_COM 45 -#define STM32_DMAMUX1_TIM16_UP 46 -#define STM32_DMAMUX1_TIM17_CH1 47 -#define STM32_DMAMUX1_TIM17_COM 48 -#define STM32_DMAMUX1_TIM17_UP 49 -#define STM32_DMAMUX1_USART1_RX 50 -#define STM32_DMAMUX1_USART1_TX 51 -#define STM32_DMAMUX1_USART2_RX 52 -#define STM32_DMAMUX1_USART2_TX 53 -#define STM32_DMAMUX1_USART3_RX 54 -#define STM32_DMAMUX1_USART3_TX 55 -#define STM32_DMAMUX1_USART4_RX 56 -#define STM32_DMAMUX1_USART4_TX 57 -#define STM32_DMAMUX1_UART4_RX STM32_DMAMUX1_USART4_RX /* Legacy. */ -#define STM32_DMAMUX1_UART4_TX STM32_DMAMUX1_USART4_TX /* Legacy. */ -#define STM32_DMAMUX1_UCPD1_RX 58 -#define STM32_DMAMUX1_UCPD1_TX 59 -#define STM32_DMAMUX1_UCPD2_RX 60 -#define STM32_DMAMUX1_UCPD2_TX 61 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMAMUX_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx/stm32_dmamux.h + * @brief STM32G0xx DMAMUX handler header. + * + * @addtogroup STM32G0xx_DMAMUX + * @{ + */ + +#ifndef STM32_DMAMUX_H +#define STM32_DMAMUX_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name DMAMUX1 request sources + * @{ + */ +#define STM32_DMAMUX1_REQ_GEN0 1 +#define STM32_DMAMUX1_REQ_GEN1 2 +#define STM32_DMAMUX1_REQ_GEN2 3 +#define STM32_DMAMUX1_REQ_GEN3 4 +#define STM32_DMAMUX1_ADC1 5 +#define STM32_DMAMUX1_AES_IN 6 +#define STM32_DMAMUX1_AES_OUT 7 +#define STM32_DMAMUX1_DAC1_CH1 8 +#define STM32_DMAMUX1_DAC1_CH2 9 +#define STM32_DMAMUX1_I2C1_RX 10 +#define STM32_DMAMUX1_I2C1_TX 11 +#define STM32_DMAMUX1_I2C2_RX 12 +#define STM32_DMAMUX1_I2C2_TX 13 +#define STM32_DMAMUX1_LPUART1_RX 14 +#define STM32_DMAMUX1_LPUART1_TX 15 +#define STM32_DMAMUX1_SPI1_RX 16 +#define STM32_DMAMUX1_SPI1_TX 17 +#define STM32_DMAMUX1_SPI2_RX 18 +#define STM32_DMAMUX1_SPI2_TX 19 +#define STM32_DMAMUX1_TIM1_CH1 20 +#define STM32_DMAMUX1_TIM1_CH2 21 +#define STM32_DMAMUX1_TIM1_CH3 22 +#define STM32_DMAMUX1_TIM1_CH4 23 +#define STM32_DMAMUX1_TIM1_COM 24 +#define STM32_DMAMUX1_TIM1_UP 25 +#define STM32_DMAMUX1_TIM2_CH1 26 +#define STM32_DMAMUX1_TIM2_CH2 27 +#define STM32_DMAMUX1_TIM2_CH3 28 +#define STM32_DMAMUX1_TIM2_CH4 29 +#define STM32_DMAMUX1_TIM2_TRIG 30 +#define STM32_DMAMUX1_TIM2_UP 31 +#define STM32_DMAMUX1_TIM3_CH1 32 +#define STM32_DMAMUX1_TIM3_CH2 33 +#define STM32_DMAMUX1_TIM3_CH3 34 +#define STM32_DMAMUX1_TIM3_CH4 35 +#define STM32_DMAMUX1_TIM3_TRIG 36 +#define STM32_DMAMUX1_TIM3_UP 37 +#define STM32_DMAMUX1_TIM6_UP 38 +#define STM32_DMAMUX1_TIM7_UP 39 +#define STM32_DMAMUX1_TIM15_CH1 40 +#define STM32_DMAMUX1_TIM15_CH2 41 +#define STM32_DMAMUX1_TIM15_COM 42 +#define STM32_DMAMUX1_TIM15_UP 43 +#define STM32_DMAMUX1_TIM16_CH1 44 +#define STM32_DMAMUX1_TIM16_COM 45 +#define STM32_DMAMUX1_TIM16_UP 46 +#define STM32_DMAMUX1_TIM17_CH1 47 +#define STM32_DMAMUX1_TIM17_COM 48 +#define STM32_DMAMUX1_TIM17_UP 49 +#define STM32_DMAMUX1_USART1_RX 50 +#define STM32_DMAMUX1_USART1_TX 51 +#define STM32_DMAMUX1_USART2_RX 52 +#define STM32_DMAMUX1_USART2_TX 53 +#define STM32_DMAMUX1_USART3_RX 54 +#define STM32_DMAMUX1_USART3_TX 55 +#define STM32_DMAMUX1_USART4_RX 56 +#define STM32_DMAMUX1_USART4_TX 57 +#define STM32_DMAMUX1_UART4_RX STM32_DMAMUX1_USART4_RX /* Legacy. */ +#define STM32_DMAMUX1_UART4_TX STM32_DMAMUX1_USART4_TX /* Legacy. */ +#define STM32_DMAMUX1_UCPD1_RX 58 +#define STM32_DMAMUX1_UCPD1_TX 59 +#define STM32_DMAMUX1_UCPD2_RX 60 +#define STM32_DMAMUX1_UCPD2_TX 61 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMAMUX_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/stm32_isr.c b/os/hal/ports/STM32/STM32G0xx/stm32_isr.c index 131b33a38e..794e8c2025 100644 --- a/os/hal/ports/STM32/STM32G0xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32G0xx/stm32_isr.c @@ -1,134 +1,134 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx/stm32_isr.c - * @brief STM32G0xx ISR handler code. - * - * @addtogroup STM32G0xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_dma1_ch23.inc" -#include "stm32_dma1_ch4567.inc" - -#include "stm32_exti0_1.inc" -#include "stm32_exti2_3.inc" -#include "stm32_exti4_15.inc" -#include "stm32_exti19-21.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart3_4_lp1.inc" - -#include "stm32_tim1.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim14.inc" -#include "stm32_tim15.inc" -#include "stm32_tim16.inc" -#include "stm32_tim17.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_1_irq_init(); - exti2_3_irq_init(); - exti4_15_irq_init(); - exti19_exti21_irq_init(); - - tim1_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim14_irq_init(); - tim15_irq_init(); - tim16_irq_init(); - tim17_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_usart4_lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_1_irq_deinit(); - exti2_3_irq_deinit(); - exti4_15_irq_deinit(); - exti19_exti21_irq_deinit(); - - tim1_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim14_irq_deinit(); - tim15_irq_deinit(); - tim16_irq_deinit(); - tim17_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_usart4_lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx/stm32_isr.c + * @brief STM32G0xx ISR handler code. + * + * @addtogroup STM32G0xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_dma1_ch23.inc" +#include "stm32_dma1_ch4567.inc" + +#include "stm32_exti0_1.inc" +#include "stm32_exti2_3.inc" +#include "stm32_exti4_15.inc" +#include "stm32_exti19-21.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart3_4_lp1.inc" + +#include "stm32_tim1.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim14.inc" +#include "stm32_tim15.inc" +#include "stm32_tim16.inc" +#include "stm32_tim17.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_1_irq_init(); + exti2_3_irq_init(); + exti4_15_irq_init(); + exti19_exti21_irq_init(); + + tim1_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim14_irq_init(); + tim15_irq_init(); + tim16_irq_init(); + tim17_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_usart4_lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_1_irq_deinit(); + exti2_3_irq_deinit(); + exti4_15_irq_deinit(); + exti19_exti21_irq_deinit(); + + tim1_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim14_irq_deinit(); + tim15_irq_deinit(); + tim16_irq_deinit(); + tim17_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_usart4_lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/stm32_isr.h b/os/hal/ports/STM32/STM32G0xx/stm32_isr.h index 2e833f28bc..2baf0da48d 100644 --- a/os/hal/ports/STM32/STM32G0xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32G0xx/stm32_isr.h @@ -1,182 +1,182 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx/stm32_isr.h - * @brief STM32G0xx ISR handler header. - * - * @addtogroup STM32G0xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM14_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC unit. - */ -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 - -/* - * DMA unit. - */ -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C - -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH4567_NUMBER 11 -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER - -#define STM32_DMA1_CH1_CMASK 0x00000001U -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* - * EXTI unit. - */ -#define STM32_EXTI0_1_HANDLER Vector54 -#define STM32_EXTI2_3_HANDLER Vector58 -#define STM32_EXTI4_15_HANDLER Vector5C -#define STM32_EXTI16_HANDLER Vector44 -#define STM32_EXTI1921_HANDLER Vector48 - -#define STM32_EXTI0_1_NUMBER 5 -#define STM32_EXTI2_3_NUMBER 6 -#define STM32_EXTI4_15_NUMBER 7 -#define STM32_EXTI6_NUMBER 1 -#define STM32_EXTI1921_NUMBER 2 - -/* - * I2C units. - */ -#define STM32_I2C1_GLOBAL_HANDLER Vector9C -#define STM32_I2C2_GLOBAL_HANDLER VectorA0 - -#define STM32_I2C1_GLOBAL_NUMBER 23 -#define STM32_I2C2_GLOBAL_NUMBER 24 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER Vector74 -#define STM32_TIM1_CC_HANDLER Vector78 -#define STM32_TIM2_HANDLER Vector7C -#define STM32_TIM3_HANDLER Vector80 -#define STM32_TIM6_HANDLER Vector84 -#define STM32_TIM7_HANDLER Vector88 -#define STM32_TIM14_HANDLER Vector8C -#define STM32_TIM15_HANDLER Vector90 -#define STM32_TIM16_HANDLER Vector94 -#define STM32_TIM17_HANDLER Vector98 - -#define STM32_TIM1_UP_NUMBER 13 -#define STM32_TIM1_CC_NUMBER 14 -#define STM32_TIM2_NUMBER 15 -#define STM32_TIM3_NUMBER 16 -#define STM32_TIM6_NUMBER 17 -#define STM32_TIM7_NUMBER 18 -#define STM32_TIM14_NUMBER 19 -#define STM32_TIM15_NUMBER 20 -#define STM32_TIM16_NUMBER 21 -#define STM32_TIM17_NUMBER 22 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorAC -#define STM32_USART2_HANDLER VectorB0 -#define STM32_USART3_4_LP1_HANDLER VectorB4 - -#define STM32_USART1_NUMBER 27 -#define STM32_USART2_NUMBER 28 -#define STM32_USART3_4_LP1_NUMBER 29 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx/stm32_isr.h + * @brief STM32G0xx ISR handler header. + * + * @addtogroup STM32G0xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM14_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC unit. + */ +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 + +/* + * DMA unit. + */ +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C + +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH4567_NUMBER 11 +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER + +#define STM32_DMA1_CH1_CMASK 0x00000001U +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* + * EXTI unit. + */ +#define STM32_EXTI0_1_HANDLER Vector54 +#define STM32_EXTI2_3_HANDLER Vector58 +#define STM32_EXTI4_15_HANDLER Vector5C +#define STM32_EXTI16_HANDLER Vector44 +#define STM32_EXTI1921_HANDLER Vector48 + +#define STM32_EXTI0_1_NUMBER 5 +#define STM32_EXTI2_3_NUMBER 6 +#define STM32_EXTI4_15_NUMBER 7 +#define STM32_EXTI6_NUMBER 1 +#define STM32_EXTI1921_NUMBER 2 + +/* + * I2C units. + */ +#define STM32_I2C1_GLOBAL_HANDLER Vector9C +#define STM32_I2C2_GLOBAL_HANDLER VectorA0 + +#define STM32_I2C1_GLOBAL_NUMBER 23 +#define STM32_I2C2_GLOBAL_NUMBER 24 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER Vector74 +#define STM32_TIM1_CC_HANDLER Vector78 +#define STM32_TIM2_HANDLER Vector7C +#define STM32_TIM3_HANDLER Vector80 +#define STM32_TIM6_HANDLER Vector84 +#define STM32_TIM7_HANDLER Vector88 +#define STM32_TIM14_HANDLER Vector8C +#define STM32_TIM15_HANDLER Vector90 +#define STM32_TIM16_HANDLER Vector94 +#define STM32_TIM17_HANDLER Vector98 + +#define STM32_TIM1_UP_NUMBER 13 +#define STM32_TIM1_CC_NUMBER 14 +#define STM32_TIM2_NUMBER 15 +#define STM32_TIM3_NUMBER 16 +#define STM32_TIM6_NUMBER 17 +#define STM32_TIM7_NUMBER 18 +#define STM32_TIM14_NUMBER 19 +#define STM32_TIM15_NUMBER 20 +#define STM32_TIM16_NUMBER 21 +#define STM32_TIM17_NUMBER 22 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorAC +#define STM32_USART2_HANDLER VectorB0 +#define STM32_USART3_4_LP1_HANDLER VectorB4 + +#define STM32_USART1_NUMBER 27 +#define STM32_USART2_NUMBER 28 +#define STM32_USART3_4_LP1_NUMBER 29 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/stm32_rcc.h b/os/hal/ports/STM32/STM32G0xx/stm32_rcc.h index 3927dea5cb..28c7563664 100644 --- a/os/hal/ports/STM32/STM32G0xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32G0xx/stm32_rcc.h @@ -1,869 +1,869 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32g0xx.h. - * - * @addtogroup STM32G0xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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 APB bus (R1). - * - * @param[in] mask APB R1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPBR1(mask, lp) { \ - RCC->APBENR1 |= (mask); \ - if (lp) \ - RCC->APBSMENR1 |= (mask); \ - else \ - RCC->APBSMENR1 &= ~(mask); \ - (void)RCC->APBSMENR1; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB bus (R1). - * - * @param[in] mask APB R1 peripherals mask - * - * @api - */ -#define rccDisableAPBR1(mask) { \ - RCC->APBENR1 &= ~(mask); \ - RCC->APBSMENR1 &= ~(mask); \ - (void)RCC->APBSMENR1; \ -} - -/** - * @brief Resets one or more peripheral on the APB bus (R1). - * - * @param[in] mask APB R1 peripherals mask - * - * @api - */ -#define rccResetAPBR1(mask) { \ - RCC->APBRSTR1 |= (mask); \ - RCC->APBRSTR1 &= ~(mask); \ - (void)RCC->APBRSTR1; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB bus (R2). - * - * @param[in] mask APB R2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPBR2(mask, lp) { \ - RCC->APBENR2 |= (mask); \ - if (lp) \ - RCC->APBSMENR2 |= (mask); \ - else \ - RCC->APBSMENR2 &= ~(mask); \ - (void)RCC->APBSMENR2; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB bus (R2). - * - * @param[in] mask APB R2 peripherals mask - * - * @api - */ -#define rccDisableAPBR2(mask) { \ - RCC->APBENR2 &= ~(mask); \ - RCC->APBSMENR2 &= ~(mask); \ - (void)RCC->APBSMENR2; \ -} - -/** - * @brief Resets one or more peripheral on the APB bus (R2). - * - * @param[in] mask APB R2 peripherals mask - * - * @api - */ -#define rccResetAPBR2(mask) { \ - RCC->APBRSTR2 |= (mask); \ - RCC->APBRSTR2 &= ~(mask); \ - (void)RCC->APBRSTR2; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the IOP bus. - * - * @param[in] mask IOP peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableIOP(mask, lp) { \ - RCC->IOPENR |= (mask); \ - if (lp) \ - RCC->IOPSMENR |= (mask); \ - else \ - RCC->IOPSMENR &= ~(mask); \ - (void)RCC->IOPSMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the IOP bus. - * - * @param[in] mask IOP peripherals mask - * - * @api - */ -#define rccDisableIOP(mask) { \ - RCC->IOPENR &= ~(mask); \ - RCC->IOPSMENR &= ~(mask); \ - (void)RCC->IOPSMENR; \ -} - -/** - * @brief Resets one or more peripheral on the IOP bus. - * - * @param[in] mask IOP peripherals mask - * - * @api - */ -#define rccResetIOP(mask) { \ - RCC->IOPRSTR |= (mask); \ - RCC->IOPRSTR &= ~(mask); \ - (void)RCC->IOPRSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - if (lp) \ - RCC->AHBSMENR |= (mask); \ - else \ - RCC->AHBSMENR &= ~(mask); \ - (void)RCC->AHBSMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - RCC->AHBSMENR &= ~(mask); \ - (void)RCC->AHBSMENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPBR2(RCC_APBENR2_ADCEN, lp) - -/** - * @brief Disables the ADC peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPBR2(RCC_APBENR2_ADCEN) - -/** - * @brief Resets the ADC peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPBR2(RCC_APBRSTR2_ADCRST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPBR1(RCC_APBENR1_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPBR1(RCC_APBENR1_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPBR1(RCC_APBRSTR1_DAC1RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) -/** @} */ - -/** - * @name DMAMUX peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMAMUX peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMAMUX(lp) - -/** - * @brief Disables the DMAMUX peripheral clock. - * - * @api - */ -#define rccDisableDMAMUX() - -/** - * @brief Resets the DMAMUX peripheral. - * - * @api - */ -#define rccResetDMAMUX() -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPBR1(RCC_APBENR1_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPBR1(RCC_APBENR1_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPBR1(RCC_APBRSTR1_PWRRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPBR1(RCC_APBENR1_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPBR1(RCC_APBENR1_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPBR1(RCC_APBRSTR1_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPBR1(RCC_APBENR1_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPBR1(RCC_APBENR1_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPBR1(RCC_APBRSTR1_I2C2RST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB(RCC_AHBENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB(RCC_AHBENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB(RCC_AHBRSTR_RNGRST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPBR2(RCC_APBENR2_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPBR2(RCC_APBENR2_SPI1EN) - -/** - * @brief Resets the SPI1 peripheral. - * - * @api - */ -#define rccResetSPI1() rccResetAPB(RCC_APBRSTR2_SPI1RST) - -/** - * @brief Enables the SPI2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI2(lp) rccEnableAPBR1(RCC_APBENR1_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPBR1(RCC_APBENR1_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPBR1(RCC_APBRSTR1_SPI2RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPBR2(RCC_APBENR2_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPBR2(RCC_APBENR2_TIM1EN) - -/** - * @brief Resets the TIM1 peripheral. - * - * @api - */ -#define rccResetTIM1() rccResetAPBR2(RCC_APBRSTR2_TIM1RST) - -/** - * @brief Enables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPBR1(RCC_APBENR1_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPBR1(RCC_APBENR1_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPBR1(RCC_APBRSTR1_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPBR1(RCC_APBENR1_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPBR1(RCC_APBENR1_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPBR1(RCC_APBRSTR1_TIM3RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPBR1(RCC_APBENR1_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPBR1(RCC_APBENR1_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPBR1(RCC_APBRSTR1_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPBR1(RCC_APBENR1_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPBR1(RCC_APBENR1_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPBR1(RCC_APBRSTR1_TIM7RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPBR2(RCC_APBENR2_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPBR2(RCC_APBENR2_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPBR2(RCC_APBRSTR2_TIM14RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPBR2(RCC_APBENR2_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPBR2(RCC_APBENR2_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPBR2(RCC_APBRSTR2_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB(RCC_APBENR2_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPBR2(RCC_APBENR2_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPBR2(RCC_APBRSTR2_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPBR2(RCC_APBENR2_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPBR2(RCC_APBENR2_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPBR2(RCC_APBRSTR2_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPBR2(RCC_APBENR2_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPBR2(RCC_APBENR2_USART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetUSART1() rccResetAPBR2(RCC_APBRSTR2_USART1RST) - -/** - * @brief Enables the USART2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART2(lp) rccEnableAPBR1(RCC_APBENR1_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPBR1(RCC_APBENR1_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPBR1(RCC_APBRSTR1_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPBR1(RCC_APBENR1_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPBR1(RCC_APBENR1_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPBR1(RCC_APBRSTR1_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPBR1(RCC_APBENR1_USART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPBR1(RCC_APBENR1_USART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPBR1(RCC_APBRSTR1_USART4RST) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPBR1(RCC_APBENR1_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPBR1(RCC_APBENR1_LPUART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPBR1(RCC_APBRSTR1_LPUART1RST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32g0xx.h. + * + * @addtogroup STM32G0xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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 APB bus (R1). + * + * @param[in] mask APB R1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPBR1(mask, lp) { \ + RCC->APBENR1 |= (mask); \ + if (lp) \ + RCC->APBSMENR1 |= (mask); \ + else \ + RCC->APBSMENR1 &= ~(mask); \ + (void)RCC->APBSMENR1; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB bus (R1). + * + * @param[in] mask APB R1 peripherals mask + * + * @api + */ +#define rccDisableAPBR1(mask) { \ + RCC->APBENR1 &= ~(mask); \ + RCC->APBSMENR1 &= ~(mask); \ + (void)RCC->APBSMENR1; \ +} + +/** + * @brief Resets one or more peripheral on the APB bus (R1). + * + * @param[in] mask APB R1 peripherals mask + * + * @api + */ +#define rccResetAPBR1(mask) { \ + RCC->APBRSTR1 |= (mask); \ + RCC->APBRSTR1 &= ~(mask); \ + (void)RCC->APBRSTR1; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB bus (R2). + * + * @param[in] mask APB R2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPBR2(mask, lp) { \ + RCC->APBENR2 |= (mask); \ + if (lp) \ + RCC->APBSMENR2 |= (mask); \ + else \ + RCC->APBSMENR2 &= ~(mask); \ + (void)RCC->APBSMENR2; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB bus (R2). + * + * @param[in] mask APB R2 peripherals mask + * + * @api + */ +#define rccDisableAPBR2(mask) { \ + RCC->APBENR2 &= ~(mask); \ + RCC->APBSMENR2 &= ~(mask); \ + (void)RCC->APBSMENR2; \ +} + +/** + * @brief Resets one or more peripheral on the APB bus (R2). + * + * @param[in] mask APB R2 peripherals mask + * + * @api + */ +#define rccResetAPBR2(mask) { \ + RCC->APBRSTR2 |= (mask); \ + RCC->APBRSTR2 &= ~(mask); \ + (void)RCC->APBRSTR2; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the IOP bus. + * + * @param[in] mask IOP peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableIOP(mask, lp) { \ + RCC->IOPENR |= (mask); \ + if (lp) \ + RCC->IOPSMENR |= (mask); \ + else \ + RCC->IOPSMENR &= ~(mask); \ + (void)RCC->IOPSMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the IOP bus. + * + * @param[in] mask IOP peripherals mask + * + * @api + */ +#define rccDisableIOP(mask) { \ + RCC->IOPENR &= ~(mask); \ + RCC->IOPSMENR &= ~(mask); \ + (void)RCC->IOPSMENR; \ +} + +/** + * @brief Resets one or more peripheral on the IOP bus. + * + * @param[in] mask IOP peripherals mask + * + * @api + */ +#define rccResetIOP(mask) { \ + RCC->IOPRSTR |= (mask); \ + RCC->IOPRSTR &= ~(mask); \ + (void)RCC->IOPRSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + if (lp) \ + RCC->AHBSMENR |= (mask); \ + else \ + RCC->AHBSMENR &= ~(mask); \ + (void)RCC->AHBSMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + RCC->AHBSMENR &= ~(mask); \ + (void)RCC->AHBSMENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPBR2(RCC_APBENR2_ADCEN, lp) + +/** + * @brief Disables the ADC peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPBR2(RCC_APBENR2_ADCEN) + +/** + * @brief Resets the ADC peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPBR2(RCC_APBRSTR2_ADCRST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPBR1(RCC_APBENR1_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPBR1(RCC_APBENR1_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPBR1(RCC_APBRSTR1_DAC1RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) +/** @} */ + +/** + * @name DMAMUX peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMAMUX peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMAMUX(lp) + +/** + * @brief Disables the DMAMUX peripheral clock. + * + * @api + */ +#define rccDisableDMAMUX() + +/** + * @brief Resets the DMAMUX peripheral. + * + * @api + */ +#define rccResetDMAMUX() +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPBR1(RCC_APBENR1_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPBR1(RCC_APBENR1_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPBR1(RCC_APBRSTR1_PWRRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPBR1(RCC_APBENR1_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPBR1(RCC_APBENR1_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPBR1(RCC_APBRSTR1_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPBR1(RCC_APBENR1_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPBR1(RCC_APBENR1_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPBR1(RCC_APBRSTR1_I2C2RST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB(RCC_AHBENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB(RCC_AHBENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB(RCC_AHBRSTR_RNGRST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPBR2(RCC_APBENR2_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPBR2(RCC_APBENR2_SPI1EN) + +/** + * @brief Resets the SPI1 peripheral. + * + * @api + */ +#define rccResetSPI1() rccResetAPB(RCC_APBRSTR2_SPI1RST) + +/** + * @brief Enables the SPI2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI2(lp) rccEnableAPBR1(RCC_APBENR1_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPBR1(RCC_APBENR1_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPBR1(RCC_APBRSTR1_SPI2RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPBR2(RCC_APBENR2_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPBR2(RCC_APBENR2_TIM1EN) + +/** + * @brief Resets the TIM1 peripheral. + * + * @api + */ +#define rccResetTIM1() rccResetAPBR2(RCC_APBRSTR2_TIM1RST) + +/** + * @brief Enables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPBR1(RCC_APBENR1_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPBR1(RCC_APBENR1_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPBR1(RCC_APBRSTR1_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPBR1(RCC_APBENR1_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPBR1(RCC_APBENR1_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPBR1(RCC_APBRSTR1_TIM3RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPBR1(RCC_APBENR1_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPBR1(RCC_APBENR1_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPBR1(RCC_APBRSTR1_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPBR1(RCC_APBENR1_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPBR1(RCC_APBENR1_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPBR1(RCC_APBRSTR1_TIM7RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPBR2(RCC_APBENR2_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPBR2(RCC_APBENR2_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPBR2(RCC_APBRSTR2_TIM14RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPBR2(RCC_APBENR2_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPBR2(RCC_APBENR2_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPBR2(RCC_APBRSTR2_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB(RCC_APBENR2_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPBR2(RCC_APBENR2_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPBR2(RCC_APBRSTR2_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPBR2(RCC_APBENR2_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPBR2(RCC_APBENR2_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPBR2(RCC_APBRSTR2_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPBR2(RCC_APBENR2_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPBR2(RCC_APBENR2_USART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetUSART1() rccResetAPBR2(RCC_APBRSTR2_USART1RST) + +/** + * @brief Enables the USART2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART2(lp) rccEnableAPBR1(RCC_APBENR1_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPBR1(RCC_APBENR1_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPBR1(RCC_APBRSTR1_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPBR1(RCC_APBENR1_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPBR1(RCC_APBENR1_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPBR1(RCC_APBRSTR1_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPBR1(RCC_APBENR1_USART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPBR1(RCC_APBENR1_USART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPBR1(RCC_APBRSTR1_USART4RST) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPBR1(RCC_APBENR1_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPBR1(RCC_APBENR1_LPUART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPBR1(RCC_APBRSTR1_LPUART1RST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G0xx/stm32_registry.h b/os/hal/ports/STM32/STM32G0xx/stm32_registry.h index dfccfce654..8d7bc853e4 100644 --- a/os/hal/ports/STM32/STM32G0xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32G0xx/stm32_registry.h @@ -1,455 +1,455 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G0xx/stm32_registry.h - * @brief STM32G0xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32G0xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RTC and TAMP attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 20 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_EVENT_RTC_EXTI 19 -#define STM32_RTC_EVENT_TAMP_EXTI 21 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, \ - STM32_IRQ_EXTI1921_PRIORITY); \ -} while (false) - - /* Enabling RTC-related EXTI lines.*/ -#define STM32_RTC_ENABLE_ALL_EXTI() do { \ - extiEnableGroup1(EXTI_MASK1(STM32_RTC_EVENT_RTC_EXTI) | \ - EXTI_MASK1(STM32_RTC_EVENT_TAMP_EXTI), \ - EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); \ -} while (false) - -/* Clearing EXTI interrupts. */ -#define STM32_RTC_CLEAR_ALL_EXTI() do { \ - extiClearGroup1(EXTI_MASK1(STM32_RTC_EVENT_RTC_EXTI) | \ - EXTI_MASK1(STM32_RTC_EVENT_TAMP_EXTI)); \ -} while (false) - -/* Masks used to preserve state of RTC and TAMP register reserved bits. */ -#define STM32_RTC_CR_MASK 0xE7FFFF7F -#define STM32_RTC_PRER_MASK 0x007F7FFF -#define STM32_TAMP_CR1_MASK 0x003C0003 -#define STM32_TAMP_CR2_MASK 0x030300FF -#define STM32_TAMP_FLTCR_MASK 0x000000FF -#define STM32_TAMP_IER_MASK 0x003C0003 - -#if defined(STM32G081xx) || defined(__DOXYGEN__) -#define STM32_HAS_RNG1 TRUE -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 TRUE -#else -#define STM32_HAS_RNG1 FALSE -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE -#endif - -/*===========================================================================*/ -/* STM32G070xx. */ -/*===========================================================================*/ - -#if defined(STM32G070xx) || defined(__DOXYGEN__) - -/* Errata attributes.*/ -#define STM32_HAS_TIM1617_ERRATA TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_HAS_CR TRUE -#define STM32_EXTI_SEPARATE_RF TRUE -#define STM32_EXTI_HAS_GROUP2 FALSE -#define STM32_EXTI_NUM_LINES 16 -#define STM32_EXTI_IMR1_MASK 0xFFF80000U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIODEN | \ - RCC_IOPENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* OCTOSPI attributes.*/ -#define STM32_HAS_OCTOSPI1 FALSE -#define STM32_HAS_OCTOSPI2 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 FALSE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM2 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_LPUART1 TRUE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC FALSE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI FALSE - -#endif /* defined(STM32G070xx) */ - -/*===========================================================================*/ -/* STM32G071xx STM32G081xx. */ -/*===========================================================================*/ - -#if defined(STM32G071xx) || defined(STM32G081xx) - -/* Errata attributes.*/ -#define STM32_HAS_TIM1617_ERRATA TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_HAS_CR TRUE -#define STM32_EXTI_SEPARATE_RF TRUE -#define STM32_EXTI_HAS_GROUP2 FALSE -#define STM32_EXTI_NUM_LINES 33 -#define STM32_EXTI_IMR1_MASK 0xFFF80000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFFU - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIODEN | \ - RCC_IOPENR_GPIOFEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* OCTOSPI attributes.*/ -#define STM32_HAS_OCTOSPI1 FALSE -#define STM32_HAS_OCTOSPI2 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 FALSE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_LPUART1 TRUE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC FALSE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI FALSE - -#endif /* defined(STM32G071xx) || defined(STM32G081xx) */ - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G0xx/stm32_registry.h + * @brief STM32G0xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32G0xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RTC and TAMP attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 20 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_EVENT_RTC_EXTI 19 +#define STM32_RTC_EVENT_TAMP_EXTI 21 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, \ + STM32_IRQ_EXTI1921_PRIORITY); \ +} while (false) + + /* Enabling RTC-related EXTI lines.*/ +#define STM32_RTC_ENABLE_ALL_EXTI() do { \ + extiEnableGroup1(EXTI_MASK1(STM32_RTC_EVENT_RTC_EXTI) | \ + EXTI_MASK1(STM32_RTC_EVENT_TAMP_EXTI), \ + EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); \ +} while (false) + +/* Clearing EXTI interrupts. */ +#define STM32_RTC_CLEAR_ALL_EXTI() do { \ + extiClearGroup1(EXTI_MASK1(STM32_RTC_EVENT_RTC_EXTI) | \ + EXTI_MASK1(STM32_RTC_EVENT_TAMP_EXTI)); \ +} while (false) + +/* Masks used to preserve state of RTC and TAMP register reserved bits. */ +#define STM32_RTC_CR_MASK 0xE7FFFF7F +#define STM32_RTC_PRER_MASK 0x007F7FFF +#define STM32_TAMP_CR1_MASK 0x003C0003 +#define STM32_TAMP_CR2_MASK 0x030300FF +#define STM32_TAMP_FLTCR_MASK 0x000000FF +#define STM32_TAMP_IER_MASK 0x003C0003 + +#if defined(STM32G081xx) || defined(__DOXYGEN__) +#define STM32_HAS_RNG1 TRUE +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 TRUE +#else +#define STM32_HAS_RNG1 FALSE +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE +#endif + +/*===========================================================================*/ +/* STM32G070xx. */ +/*===========================================================================*/ + +#if defined(STM32G070xx) || defined(__DOXYGEN__) + +/* Errata attributes.*/ +#define STM32_HAS_TIM1617_ERRATA TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_HAS_CR TRUE +#define STM32_EXTI_SEPARATE_RF TRUE +#define STM32_EXTI_HAS_GROUP2 FALSE +#define STM32_EXTI_NUM_LINES 16 +#define STM32_EXTI_IMR1_MASK 0xFFF80000U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIODEN | \ + RCC_IOPENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* OCTOSPI attributes.*/ +#define STM32_HAS_OCTOSPI1 FALSE +#define STM32_HAS_OCTOSPI2 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 FALSE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM2 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_LPUART1 TRUE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC FALSE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI FALSE + +#endif /* defined(STM32G070xx) */ + +/*===========================================================================*/ +/* STM32G071xx STM32G081xx. */ +/*===========================================================================*/ + +#if defined(STM32G071xx) || defined(STM32G081xx) + +/* Errata attributes.*/ +#define STM32_HAS_TIM1617_ERRATA TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_HAS_CR TRUE +#define STM32_EXTI_SEPARATE_RF TRUE +#define STM32_EXTI_HAS_GROUP2 FALSE +#define STM32_EXTI_NUM_LINES 33 +#define STM32_EXTI_IMR1_MASK 0xFFF80000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFFU + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIODEN | \ + RCC_IOPENR_GPIOFEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* OCTOSPI attributes.*/ +#define STM32_HAS_OCTOSPI1 FALSE +#define STM32_HAS_OCTOSPI2 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 FALSE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_LPUART1 TRUE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC FALSE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI FALSE + +#endif /* defined(STM32G071xx) || defined(STM32G081xx) */ + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/hal_lld.c b/os/hal/ports/STM32/STM32G4xx/hal_lld.c index 61d1e8f01b..77b4657e6f 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.c @@ -1,284 +1,284 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/hal_lld.c - * @brief STM32G4xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32g4xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing RTC clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - - /* Low speed output mode.*/ - RCC->BDCR |= STM32_LSCOSEL; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector settings.*/ - PWR->CR2 = STM32_PWR_CR2; -} - -/** - * @brief STM32L4xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB1(~0); - rccResetAHB2(~STM32_GPIO_EN_MASK); - rccResetAHB3(~0); - rccResetAPB1R1(~0); - rccResetAPB1R2(~0); - rccResetAPB2(~0); - - /* PWR clock enable.*/ -#if (HAL_USE_RTC == TRUE) && defined(RCC_APBENR1_RTCAPBEN) - rccEnableAPB1R1(RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN, false) -#else - rccEnableAPB1R1(RCC_APB1ENR1_PWREN, false) -#endif - - /* Core voltage setup.*/ - PWR->CR1 = STM32_VOS; - while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ - ; /* stable. */ - - /* Additional PWR configurations.*/ - PWR->CR2 = STM32_PWR_CR2; - PWR->CR3 = STM32_PWR_CR3; - PWR->CR4 = STM32_PWR_CR4; - PWR->CR5 = STM32_CR5BITS; - PWR->PUCRA = STM32_PWR_PUCRA; - PWR->PDCRA = STM32_PWR_PDCRA; - PWR->PUCRB = STM32_PWR_PUCRB; - PWR->PDCRB = STM32_PWR_PDCRB; - PWR->PUCRC = STM32_PWR_PUCRC; - PWR->PDCRC = STM32_PWR_PDCRC; - PWR->PUCRD = STM32_PWR_PUCRD; - PWR->PDCRD = STM32_PWR_PDCRD; - PWR->PUCRE = STM32_PWR_PUCRE; - PWR->PDCRE = STM32_PWR_PDCRE; - PWR->PUCRF = STM32_PWR_PUCRF; - PWR->PDCRF = STM32_PWR_PDCRF; - PWR->PUCRG = STM32_PWR_PUCRG; - PWR->PDCRG = STM32_PWR_PDCRG; - -#if STM32_HSI16_ENABLED - /* HSI activation.*/ - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Wait until HSI16 is stable. */ -#endif - -#if STM32_HSI48_ENABLED - /* HSI activation.*/ - RCC->CRRCR |= RCC_CRRCR_HSI48ON; - while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) - ; /* Wait until HSI48 is stable. */ -#endif - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Wait until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Wait until LSI is stable. */ -#endif - - /* Backup domain access enabled and left open.*/ - PWR->CR1 |= PWR_CR1_DBP; - -#if STM32_LSE_ENABLED - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Wait until LSE is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLLM and PLLSRC are common to all PLLs.*/ - RCC->PLLCFGR = STM32_PLLPDIV | - STM32_PLLR | STM32_PLLREN | - STM32_PLLQ | STM32_PLLQEN | - STM32_PLLP | STM32_PLLPEN | - STM32_PLLN | STM32_PLLM | - STM32_PLLSRC; -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLRDY) == 0) - ; -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_PPRE2 | STM32_PPRE1 | - STM32_HPRE; - - /* CCIPR registers initialization, note.*/ - RCC->CCIPR = STM32_ADC345SEL | STM32_ADC12SEL | STM32_CLK48SEL | - STM32_FDCANSEL | STM32_I2S23SEL | STM32_SAI1SEL | - STM32_LPTIM1SEL | STM32_I2C3SEL | STM32_I2C2SEL | - STM32_I2C1SEL | STM32_LPUART1SEL | STM32_UART5SEL | - STM32_UART4SEL | STM32_USART3SEL | STM32_USART2SEL | - STM32_USART1SEL; - RCC->CCIPR2 = STM32_QSPISEL | STM32_I2C4SEL; - - /* Set flash WS's for SYSCLK source */ - FLASH->ACR = FLASH_ACR_DBG_SWEN | FLASH_ACR_DCEN | FLASH_ACR_ICEN | - FLASH_ACR_PRFTEN | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - - /* Switching to the configured SYSCLK source if it is different from HSI16.*/ -#if STM32_SW != STM32_SW_HSI16 - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - /* Wait until SYSCLK is stable.*/ - 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); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/hal_lld.c + * @brief STM32G4xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32g4xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing RTC clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int rusefiLseCounter = 0; + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + + /* Low speed output mode.*/ + RCC->BDCR |= STM32_LSCOSEL; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector settings.*/ + PWR->CR2 = STM32_PWR_CR2; +} + +/** + * @brief STM32L4xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~0); + rccResetAHB2(~STM32_GPIO_EN_MASK); + rccResetAHB3(~0); + rccResetAPB1R1(~0); + rccResetAPB1R2(~0); + rccResetAPB2(~0); + + /* PWR clock enable.*/ +#if (HAL_USE_RTC == TRUE) && defined(RCC_APBENR1_RTCAPBEN) + rccEnableAPB1R1(RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN, false) +#else + rccEnableAPB1R1(RCC_APB1ENR1_PWREN, false) +#endif + + /* Core voltage setup.*/ + PWR->CR1 = STM32_VOS; + while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ + ; /* stable. */ + + /* Additional PWR configurations.*/ + PWR->CR2 = STM32_PWR_CR2; + PWR->CR3 = STM32_PWR_CR3; + PWR->CR4 = STM32_PWR_CR4; + PWR->CR5 = STM32_CR5BITS; + PWR->PUCRA = STM32_PWR_PUCRA; + PWR->PDCRA = STM32_PWR_PDCRA; + PWR->PUCRB = STM32_PWR_PUCRB; + PWR->PDCRB = STM32_PWR_PDCRB; + PWR->PUCRC = STM32_PWR_PUCRC; + PWR->PDCRC = STM32_PWR_PDCRC; + PWR->PUCRD = STM32_PWR_PUCRD; + PWR->PDCRD = STM32_PWR_PDCRD; + PWR->PUCRE = STM32_PWR_PUCRE; + PWR->PDCRE = STM32_PWR_PDCRE; + PWR->PUCRF = STM32_PWR_PUCRF; + PWR->PDCRF = STM32_PWR_PDCRF; + PWR->PUCRG = STM32_PWR_PUCRG; + PWR->PDCRG = STM32_PWR_PDCRG; + +#if STM32_HSI16_ENABLED + /* HSI activation.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Wait until HSI16 is stable. */ +#endif + +#if STM32_HSI48_ENABLED + /* HSI activation.*/ + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) + ; /* Wait until HSI48 is stable. */ +#endif + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Wait until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Wait until LSI is stable. */ +#endif + + /* Backup domain access enabled and left open.*/ + PWR->CR1 |= PWR_CR1_DBP; + +#if STM32_LSE_ENABLED + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Wait until LSE is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLLM and PLLSRC are common to all PLLs.*/ + RCC->PLLCFGR = STM32_PLLPDIV | + STM32_PLLR | STM32_PLLREN | + STM32_PLLQ | STM32_PLLQEN | + STM32_PLLP | STM32_PLLPEN | + STM32_PLLN | STM32_PLLM | + STM32_PLLSRC; +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLRDY) == 0) + ; +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_PPRE2 | STM32_PPRE1 | + STM32_HPRE; + + /* CCIPR registers initialization, note.*/ + RCC->CCIPR = STM32_ADC345SEL | STM32_ADC12SEL | STM32_CLK48SEL | + STM32_FDCANSEL | STM32_I2S23SEL | STM32_SAI1SEL | + STM32_LPTIM1SEL | STM32_I2C3SEL | STM32_I2C2SEL | + STM32_I2C1SEL | STM32_LPUART1SEL | STM32_UART5SEL | + STM32_UART4SEL | STM32_USART3SEL | STM32_USART2SEL | + STM32_USART1SEL; + RCC->CCIPR2 = STM32_QSPISEL | STM32_I2C4SEL; + + /* Set flash WS's for SYSCLK source */ + FLASH->ACR = FLASH_ACR_DBG_SWEN | FLASH_ACR_DCEN | FLASH_ACR_ICEN | + FLASH_ACR_PRFTEN | STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + + /* Switching to the configured SYSCLK source if it is different from HSI16.*/ +#if STM32_SW != STM32_SW_HSI16 + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + /* Wait until SYSCLK is stable.*/ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif + +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/hal_lld.h b/os/hal/ports/STM32/STM32G4xx/hal_lld.h index 8dec55553c..50bc3a0ba0 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.h @@ -1,2004 +1,2012 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/hal_lld.h - * @brief STM32G4xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32G431xx, STM32G441xx, STM32G471xx. - * - STM32G473xx, STM32G483xx. - * - STM32G474xx, STM32G484xx. - * - STM32GBK1CB. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32G431xx) || defined(STM32G441xx) || defined(STM32G471xx) || \ - defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32G4 Access Line" - -#elif defined(STM32G473xx) -#define PLATFORM_NAME "STM32G4 Performance Line" - -#elif defined(STM32G483xx) -#define PLATFORM_NAME "STM32G4 Performance Line with Crypto" - -#elif defined(STM32G474xx) -#define PLATFORM_NAME "STM32G4 Hi-resolution Line" - -#elif defined(STM32G484xx) -#define PLATFORM_NAME "STM32G4 Hi-resolution Line with Crypto" - -#elif defined(STM32GBK1CB) -#define PLATFORM_NAME "STM32G4 Mystery Line" - -#else -#error "STM32G4 device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32G4XX) || defined(__DOXYGEN__) -#define STM32G4XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSI16CLK 16000000U /**< 16MHz internal clock. */ -#define STM32_HSI48CLK 48000000U /**< 48MHz internal clock. */ -#define STM32_LSICLK 32000U /**< Low speed internal clock. */ -/** @} */ - -/** - * @name VOS field definitions - * @{ - */ -#define STM32_VOS_MASK (3U << 9U) /**< Core voltage mask. */ -#define STM32_VOS_RANGE1 (1U << 9U) /**< Core voltage 1.2 Volts. */ -#define STM32_VOS_RANGE2 (2U << 9U) /**< Core voltage 1.0 Volts. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3U << 0U) /**< SW field mask. */ -#define STM32_SW_HSI16 (1U << 0U) /**< SYSCLK source is HSI16. */ -#define STM32_SW_HSE (2U << 0U) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLLRCLK (3U << 0U) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15U << 4U) /**< HPRE field mask. */ -#define STM32_HPRE_FIELD(n) ((n) << 4U) /**< HPRE field value. */ -#define STM32_HPRE_DIV1 STM32_HPRE_FIELD(0U) -#define STM32_HPRE_DIV2 STM32_HPRE_FIELD(8U) -#define STM32_HPRE_DIV4 STM32_HPRE_FIELD(9U) -#define STM32_HPRE_DIV8 STM32_HPRE_FIELD(10U) -#define STM32_HPRE_DIV16 STM32_HPRE_FIELD(11U) -#define STM32_HPRE_DIV64 STM32_HPRE_FIELD(12U) -#define STM32_HPRE_DIV128 STM32_HPRE_FIELD(13U) -#define STM32_HPRE_DIV256 STM32_HPRE_FIELD(14U) -#define STM32_HPRE_DIV512 STM32_HPRE_FIELD(15U) - -#define STM32_PPRE1_MASK (7U << 8U) /**< PPRE1 field mask. */ -#define STM32_PPRE1_FIELD(n) ((n) << 8U) /**< PPRE1 field value. */ -#define STM32_PPRE1_DIV1 STM32_PPRE1_FIELD(0U) -#define STM32_PPRE1_DIV2 STM32_PPRE1_FIELD(4U) -#define STM32_PPRE1_DIV4 STM32_PPRE1_FIELD(5U) -#define STM32_PPRE1_DIV8 STM32_PPRE1_FIELD(6U) -#define STM32_PPRE1_DIV16 STM32_PPRE1_FIELD(7U) - -#define STM32_PPRE2_MASK (7U << 11U) /**< PPRE2 field mask. */ -#define STM32_PPRE2_FIELD(n) ((n) << 11U) /**< PPRE2 field value. */ -#define STM32_PPRE2_DIV1 STM32_PPRE2_FIELD(0U) -#define STM32_PPRE2_DIV2 STM32_PPRE2_FIELD(4U) -#define STM32_PPRE2_DIV4 STM32_PPRE2_FIELD(5U) -#define STM32_PPRE2_DIV8 STM32_PPRE2_FIELD(6U) -#define STM32_PPRE2_DIV16 STM32_PPRE2_FIELD(7U) - -#define STM32_MCOSEL_MASK (15U << 24U)/**< MCOSEL field mask. */ -#define STM32_MCOSEL_NOCLOCK (0U << 24U) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1U << 24U) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI16 (3U << 24U) /**< HSI16 clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4U << 24U) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLRCLK (5U << 24U) /**< PLLR clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6U << 24U) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7U << 24U) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_HSI48 (8U << 24U) /**< HSI48 clock on MCO pin. */ - -#define STM32_MCOPRE_MASK (7U << 28U) /**< MCOPRE field mask. */ -#define STM32_MCOPRE_FIELD(n) ((n) << 28U)/**< MCOPRE field value */ -#define STM32_MCOPRE_DIV1 STM32_MCOPRE_FIELD(0U) -#define STM32_MCOPRE_DIV2 STM32_MCOPRE_FIELD(1U) -#define STM32_MCOPRE_DIV4 STM32_MCOPRE_FIELD(2U) -#define STM32_MCOPRE_DIV8 STM32_MCOPRE_FIELD(3U) -#define STM32_MCOPRE_DIV16 STM32_MCOPRE_FIELD(4U) -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CCIPR register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3U << 0U) /**< USART1SEL mask. */ -#define STM32_USART1SEL_PCLK2 (0U << 0U) /**< USART1 source is PCLK2. */ -#define STM32_USART1SEL_SYSCLK (1U << 0U) /**< USART1 source is SYSCLK. */ -#define STM32_USART1SEL_HSI16 (2U << 0U) /**< USART1 source is HSI16. */ -#define STM32_USART1SEL_LSE (3U << 0U) /**< USART1 source is LSE. */ - -#define STM32_USART2SEL_MASK (3U << 2U) /**< USART2 mask. */ -#define STM32_USART2SEL_PCLK1 (0U << 2U) /**< USART2 source is PCLK1. */ -#define STM32_USART2SEL_SYSCLK (1U << 2U) /**< USART2 source is SYSCLK. */ -#define STM32_USART2SEL_HSI16 (2U << 2U) /**< USART2 source is HSI16. */ -#define STM32_USART2SEL_LSE (3U << 2U) /**< USART2 source is LSE. */ - -#define STM32_USART3SEL_MASK (3U << 4U) /**< USART3 mask. */ -#define STM32_USART3SEL_PCLK1 (0U << 4U) /**< USART3 source is PCLK1. */ -#define STM32_USART3SEL_SYSCLK (1U << 4U) /**< USART3 source is SYSCLK. */ -#define STM32_USART3SEL_HSI16 (2U << 4U) /**< USART3 source is HSI16. */ -#define STM32_USART3SEL_LSE (3U << 4U) /**< USART3 source is LSE. */ - -#define STM32_UART4SEL_MASK (3U << 6U) /**< UART4 mask. */ -#define STM32_UART4SEL_PCLK1 (0U << 6U) /**< UART4 source is PCLK1. */ -#define STM32_UART4SEL_SYSCLK (1U << 6U) /**< UART4 source is SYSCLK. */ -#define STM32_UART4SEL_HSI16 (2U << 6U) /**< UART4 source is HSI16. */ -#define STM32_UART4SEL_LSE (3U << 6U) /**< UART4 source is LSE. */ - -#define STM32_UART5SEL_MASK (3U << 8U) /**< UART5 mask. */ -#define STM32_UART5SEL_PCLK1 (0U << 8U) /**< UART5 source is PCLK1. */ -#define STM32_UART5SEL_SYSCLK (1U << 8U) /**< UART5 source is SYSCLK. */ -#define STM32_UART5SEL_HSI16 (2U << 8U) /**< UART5 source is HSI16. */ -#define STM32_UART5SEL_LSE (3U << 8U) /**< UART5 source is LSE. */ - -#define STM32_LPUART1SEL_MASK (3U << 10U) /**< LPUART1 mask. */ -#define STM32_LPUART1SEL_PCLK1 (0U << 10U) /**< LPUART1 source is PCLK1. */ -#define STM32_LPUART1SEL_SYSCLK (1U << 10U) /**< LPUART1 source is SYSCLK. */ -#define STM32_LPUART1SEL_HSI16 (2U << 10U) /**< LPUART1 source is HSI16. */ -#define STM32_LPUART1SEL_LSE (3U << 10U) /**< LPUART1 source is LSE. */ - -#define STM32_I2C1SEL_MASK (3U << 12U) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK1 (0U << 12U) /**< I2C1 source is PCLK1. */ -#define STM32_I2C1SEL_SYSCLK (1U << 12U) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI16 (2U << 12U) /**< I2C1 source is HSI16. */ - -#define STM32_I2C2SEL_MASK (3U << 14U) /**< I2C2SEL mask. */ -#define STM32_I2C2SEL_PCLK1 (0U << 14U) /**< I2C2 source is PCLK1. */ -#define STM32_I2C2SEL_SYSCLK (1U << 14U) /**< I2C2 source is SYSCLK. */ -#define STM32_I2C2SEL_HSI16 (2U << 14U) /**< I2C2 source is HSI16. */ - -#define STM32_I2C3SEL_MASK (3U << 16U) /**< I2C3SEL mask. */ -#define STM32_I2C3SEL_PCLK1 (0U << 16U) /**< I2C3 source is PCLK1. */ -#define STM32_I2C3SEL_SYSCLK (1U << 16U) /**< I2C3 source is SYSCLK. */ -#define STM32_I2C3SEL_HSI16 (2U << 16U) /**< I2C3 source is HSI16. */ - -#define STM32_LPTIM1SEL_MASK (3U << 18U) /**< LPTIM1SEL mask. */ -#define STM32_LPTIM1SEL_PCLK1 (0U << 18U) /**< LPTIM1 source is PCLK1. */ -#define STM32_LPTIM1SEL_LSI (1U << 18U) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_HSI16 (2U << 18U) /**< LPTIM1 source is HSI16. */ -#define STM32_LPTIM1SEL_LSE (3U << 18U) /**< LPTIM1 source is LSE. */ - -#define STM32_SAI1SEL_MASK (3U << 20U) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_SYSCLK (0U << 20U) /**< SAI1 source is SYSCLK. */ -#define STM32_SAI1SEL_PLLQCLK (1U << 20U) /**< SAI1 source is PLLQCLK. */ -#define STM32_SAI1SEL_CKIN (2U << 20U) /**< SAI1 source is CKIN. */ -#define STM32_SAI1SEL_HSI16 (3U << 20U) /**< SAI1 source is HSI16. */ - -#define STM32_I2S23SEL_MASK (3U << 22U) /**< I2S23SEL mask. */ -#define STM32_I2S23SEL_SYSCLK (0U << 22U) /**< I2S23 source is SYSCLK. */ -#define STM32_I2S23SEL_PLLQCLK (1U << 22U) /**< I2S23 source is PLLQCLK. */ -#define STM32_I2S23SEL_CKIN (2U << 22U) /**< I2S23 source is CKIN. */ -#define STM32_I2S23SEL_HSI16 (3U << 22U) /**< I2S23 source is HSI16. */ - -#define STM32_FDCANSEL_MASK (3U << 24U) /**< FDCANSEL mask. */ -#define STM32_FDCANSEL_HSE (0U << 24U) /**< FDCAN source is HSE. */ -#define STM32_FDCANSEL_PLLQCLK (1U << 24U) /**< FDCAN source is PLLQCLK. */ -#define STM32_FDCANSEL_PCLK1 (2U << 24U) /**< FDCAN source is PCLK1. */ - -#define STM32_CLK48SEL_MASK (3U << 26U) /**< CLK48SEL mask. */ -#define STM32_CLK48SEL_HSI48 (0U << 26U) /**< CLK48 source is HSI48. */ -#define STM32_CLK48SEL_PLLQCLK (2U << 26U) /**< CLK48 source is PLLQCLK. */ - -#define STM32_ADC12SEL_MASK (3U << 28U) /**< ADC12SEL mask. */ -#define STM32_ADC12SEL_NOCLK (0U << 28U) /**< ADC12 source is none. */ -#define STM32_ADC12SEL_PLLPCLK (1U << 28U) /**< ADC12 source is PLLPCLK. */ -#define STM32_ADC12SEL_SYSCLK (2U << 28U) /**< ADC12 source is SYSCLK. */ - -#define STM32_ADC345SEL_MASK (3U << 30U) /**< ADC345SEL mask. */ -#define STM32_ADC345SEL_NOCLK (0U << 30U) /**< ADC345 source is none. */ -#define STM32_ADC345SEL_PLLPCLK (1U << 30U) /**< ADC345 source is PLLPCLK. */ -#define STM32_ADC345SEL_SYSCLK (2U << 30U) /**< ADC345 source is SYSCLK. */ -/** @} */ - -/** - * @name RCC_CCIPR2 register bits definitions - * @{ - */ -#define STM32_I2C4SEL_MASK (3U << 0U) /**< I2C4SEL mask. */ -#define STM32_I2C4SEL_PCLK1 (0U << 0U) /**< I2C4 source is PCLK1. */ -#define STM32_I2C4SEL_SYSCLK (1U << 0U) /**< I2C4 source is SYSCLK. */ -#define STM32_I2C4SEL_HSI16 (2U << 0U) /**< I2C4 source is HSI16. */ - -#define STM32_QSPISEL_MASK (3U << 20U) /**< QSPISEL mask. */ -#define STM32_QSPISEL_SYSCLK (0U << 20U) /**< QSPI source is SYSCLK. */ -#define STM32_QSPISEL_HSI16 (1U << 20U) /**< QSPI source is HSI16. */ -#define STM32_QSPISEL_PLLQCLK (2U << 20U) /**< QSPI source is PLLQCLK. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3U << 8U) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0U << 8U) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1U << 8U) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2U << 8U) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3U << 8U) /**< RTC source is HSE divided. */ - -#define STM32_LSCOSEL_MASK (3U << 24U) /**< LSCO pin clock source. */ -#define STM32_LSCOSEL_NOCLOCK (0U << 24U) /**< No clock on LSCO pin. */ -#define STM32_LSCOSEL_LSI (1U << 24U) /**< LSI on LSCO pin. */ -#define STM32_LSCOSEL_LSE (3U << 24U) /**< LSE on LSCO pin. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_RANGE1 -#endif - -/** - * @brief Core voltage boost. - * @note The boost can only be used when STM32_VOS==STM32_VOS_RANGE1. - */ -#if !defined(STM32_PWR_BOOST) || defined(__DOXYGEN__) -#define STM32_PWR_BOOST TRUE -#endif - -/** - * @brief PWR CR2 register initialization value. - */ -#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) -#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0) -#endif - -/** - * @brief PWR CR3 register initialization value. - */ -#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__) -#define STM32_PWR_CR3 (PWR_CR3_EIWF) -#endif - -/** - * @brief PWR CR4 register initialization value. - */ -#if !defined(STM32_PWR_CR4) || defined(__DOXYGEN__) -#define STM32_PWR_CR4 (0U) -#endif - -/** - * @brief PWR PUCRA register initialization value. - */ -#if !defined(STM32_PWR_PUCRA) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRA (0U) -#endif - -/** - * @brief PWR PDCRA register initialization value. - */ -#if !defined(STM32_PWR_PDCRA) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRA (0U) -#endif - -/** - * @brief PWR PUCRB register initialization value. - */ -#if !defined(STM32_PWR_PUCRB) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRB (0U) -#endif - -/** - * @brief PWR PDCRB register initialization value. - */ -#if !defined(STM32_PWR_PDCRB) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRB (0U) -#endif - -/** - * @brief PWR PUCRC register initialization value. - */ -#if !defined(STM32_PWR_PUCRC) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRC (0U) -#endif - -/** - * @brief PWR PDCRC register initialization value. - */ -#if !defined(STM32_PWR_PDCRC) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRC (0U) -#endif - -/** - * @brief PWR PUCRD register initialization value. - */ -#if !defined(STM32_PWR_PUCRD) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRD (0U) -#endif - -/** - * @brief PWR PDCRD register initialization value. - */ -#if !defined(STM32_PWR_PDCRD) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRD (0U) -#endif - -/** - * @brief PWR PUCRE register initialization value. - */ -#if !defined(STM32_PWR_PUCRE) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRE (0U) -#endif - -/** - * @brief PWR PDCRE register initialization value. - */ -#if !defined(STM32_PWR_PDCRE) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRE (0U) -#endif - -/** - * @brief PWR PUCRF register initialization value. - */ -#if !defined(STM32_PWR_PUCRF) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRF (0U) -#endif - -/** - * @brief PWR PDCRF register initialization value. - */ -#if !defined(STM32_PWR_PDCRF) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRF (0U) -#endif - -/** - * @brief PWR PUCRG register initialization value. - */ -#if !defined(STM32_PWR_PUCRG) || defined(__DOXYGEN__) -#define STM32_PWR_PUCRG (0U) -#endif - -/** - * @brief PWR PDCRG register initialization value. - */ -#if !defined(STM32_PWR_PDCRG) || defined(__DOXYGEN__) -#define STM32_PWR_PDCRG (0U) -#endif - -/** - * @brief Enables or disables the HSI16 clock source. - */ -#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSI48 clock source. - */ -#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI48_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 170MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLLRCLK -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 170MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 170MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 4 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 8..127. - * @note The default value is calculated for a 170MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 84 -#endif - -/** - * @brief PLLPDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLPDIV_VALUE 0 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 7 -#endif - -/** - * @brief PLLQ divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 8 -#endif - -/** - * @brief PLLR divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 170MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLR_VALUE 2 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 170MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief LSCO clock source. - */ -#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) -#define STM32_UART5SEL STM32_UART5SEL_SYSCLK -#endif - -/** - * @brief LPUART1 clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) -#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 -#endif - -/** - * @brief I2C3 clock source. - */ -#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) -#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 -#endif - -/** - * @brief I2C4 clock source. - */ -#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) -#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#endif - -/** - * @brief SAI1 clock source. - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK -#endif - -/** - * @brief I2S23 clock source. - */ -#if !defined(STM32_I2S23SEL) || defined(__DOXYGEN__) -#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK -#endif - -/** - * @brief FDCAN clock source. - */ -#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__) -#define STM32_FDCANSEL STM32_FDCANSEL_HSE -#endif - -/** - * @brief CLK48 clock source. - */ -#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) -#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 -#endif - -/** - * @brief ADC12 clock source. - */ -#if !defined(STM32_ADC12SEL) || defined(__DOXYGEN__) -#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK -#endif - -/** - * @brief ADC34 clock source. - */ -#if !defined(STM32_ADC345SEL) || defined(__DOXYGEN__) -#define STM32_ADC345SEL STM32_ADC345SEL_PLLPCLK -#endif - -/** - * @brief QSPI clock source. - */ -#if !defined(STM32_QSPISEL) || defined(__DOXYGEN__) -#define STM32_QSPISEL STM32_QSPISEL_SYSCLK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Boost mode checks.*/ -#if STM32_PWR_BOOST && (STM32_VOS != STM32_VOS_RANGE1) -#error "STM32_PWR_BOOST requires STM32_VOS_RANGE1" -#endif - -/* - * Configuration-related checks. - */ -#if !defined(STM32G4xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G4xx_MCUCONF not defined" -#endif - -#if defined(STM32G431xx) && !defined(STM32G431_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G431_MCUCONF not defined" - -#elif defined(STM32G441xx) && !defined(STM32G441_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G441_MCUCONF not defined" - -#elif defined(STM32G471xx) && !defined(STM32G471_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G471_MCUCONF not defined" - -#elif defined(STM32G473xx) && !defined(STM32G473_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G473_MCUCONF not defined" - -#elif defined(STM32G483xx) && !defined(STM32G473_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G483_MCUCONF not defined" - -#elif defined(STM32G474xx) && !defined(STM32G474_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G474_MCUCONF not defined" - -#elif defined(STM32G484xx) && !defined(STM32G484_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32G484_MCUCONF not defined" - -#elif defined(STM32GBK1CB) && !defined(STM32GBK1CB_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32GBK1CB_MCUCONF not defined" - -#endif - -/* - * Board files sanity checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif - -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/** - * @name System Limits for VOS range 1 with boost - * @{ - */ -#define STM32_BOOST_SYSCLK_MAX 170000000 -#define STM32_BOOST_HSECLK_MAX 48000000 -#define STM32_BOOST_HSECLK_BYP_MAX 48000000 -#define STM32_BOOST_HSECLK_MIN 8000000 -#define STM32_BOOST_HSECLK_BYP_MIN 8000000 -#define STM32_BOOST_LSECLK_MAX 32768 -#define STM32_BOOST_LSECLK_BYP_MAX 1000000 -#define STM32_BOOST_LSECLK_MIN 32768 -#define STM32_BOOST_LSECLK_BYP_MIN 32768 -#define STM32_BOOST_PLLIN_MAX 16000000 -#define STM32_BOOST_PLLIN_MIN 2660000 -#define STM32_BOOST_PLLVCO_MAX 344000000 -#define STM32_BOOST_PLLVCO_MIN 96000000 -#define STM32_BOOST_PLLP_MAX 170000000 -#define STM32_BOOST_PLLP_MIN 2064500 -#define STM32_BOOST_PLLQ_MAX 170000000 -#define STM32_BOOST_PLLQ_MIN 8000000 -#define STM32_BOOST_PLLR_MAX 170000000 -#define STM32_BOOST_PLLR_MIN 8000000 -#define STM32_BOOST_PCLK1_MAX 170000000 -#define STM32_BOOST_PCLK2_MAX 170000000 -#define STM32_BOOST_ADCCLK_MAX 60000000 - -#define STM32_BOOST_0WS_THRESHOLD 34000000 -#define STM32_BOOST_1WS_THRESHOLD 68000000 -#define STM32_BOOST_2WS_THRESHOLD 102000000 -#define STM32_BOOST_3WS_THRESHOLD 136000000 -#define STM32_BOOST_4WS_THRESHOLD 170000000 -/** @} */ - -/** - * @name System Limits for VOS range 1 without boost - * @{ - */ -#define STM32_VOS1_SYSCLK_MAX 150000000 -#define STM32_VOS1_HSECLK_MAX 48000000 -#define STM32_VOS1_HSECLK_BYP_MAX 48000000 -#define STM32_VOS1_HSECLK_MIN 8000000 -#define STM32_VOS1_HSECLK_BYP_MIN 8000000 -#define STM32_VOS1_LSECLK_MAX 32768 -#define STM32_VOS1_LSECLK_BYP_MAX 1000000 -#define STM32_VOS1_LSECLK_MIN 32768 -#define STM32_VOS1_LSECLK_BYP_MIN 32768 -#define STM32_VOS1_PLLIN_MAX 16000000 -#define STM32_VOS1_PLLIN_MIN 2660000 -#define STM32_VOS1_PLLVCO_MAX 344000000 -#define STM32_VOS1_PLLVCO_MIN 96000000 -#define STM32_VOS1_PLLP_MAX 150000000 -#define STM32_VOS1_PLLP_MIN 2064500 -#define STM32_VOS1_PLLQ_MAX 150000000 -#define STM32_VOS1_PLLQ_MIN 8000000 -#define STM32_VOS1_PLLR_MAX 150000000 -#define STM32_VOS1_PLLR_MIN 8000000 -#define STM32_VOS1_PCLK1_MAX 150000000 -#define STM32_VOS1_PCLK2_MAX 150000000 -#define STM32_VOS1_ADCCLK_MAX 60000000 - -#define STM32_VOS1_0WS_THRESHOLD 30000000 -#define STM32_VOS1_1WS_THRESHOLD 60000000 -#define STM32_VOS1_2WS_THRESHOLD 90000000 -#define STM32_VOS1_3WS_THRESHOLD 120000000 -#define STM32_VOS1_4WS_THRESHOLD 150000000 -/** @} */ - -/** - * @name System Limits for VOS range 2 - * @{ - */ -#define STM32_VOS2_SYSCLK_MAX 26000000 -#define STM32_VOS2_HSECLK_MAX 26000000 -#define STM32_VOS2_HSECLK_BYP_MAX 26000000 -#define STM32_VOS2_HSECLK_MIN 8000000 -#define STM32_VOS2_HSECLK_BYP_MIN 8000000 -#define STM32_VOS2_LSECLK_MAX 32768 -#define STM32_VOS2_LSECLK_BYP_MAX 1000000 -#define STM32_VOS2_LSECLK_MIN 32768 -#define STM32_VOS2_LSECLK_BYP_MIN 32768 -#define STM32_VOS2_PLLIN_MAX 16000000 -#define STM32_VOS2_PLLIN_MIN 2660000 -#define STM32_VOS2_PLLVCO_MAX 128000000 -#define STM32_VOS2_PLLVCO_MIN 96000000 -#define STM32_VOS2_PLLP_MAX 26000000 -#define STM32_VOS2_PLLP_MIN 2064500 -#define STM32_VOS2_PLLQ_MAX 26000000 -#define STM32_VOS2_PLLQ_MIN 8000000 -#define STM32_VOS2_PLLR_MAX 26000000 -#define STM32_VOS2_PLLR_MIN 8000000 -#define STM32_VOS2_PCLK1_MAX 26000000 -#define STM32_VOS2_PCLK2_MAX 26000000 -#define STM32_VOS2_ADCCLK_MAX 26000000 - -#define STM32_VOS2_0WS_THRESHOLD 12000000 -#define STM32_VOS2_1WS_THRESHOLD 24000000 -#define STM32_VOS2_2WS_THRESHOLD 26000000 -#define STM32_VOS2_3WS_THRESHOLD 0 -#define STM32_VOS2_4WS_THRESHOLD 0 -/** @} */ - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) -#if STM32_PWR_BOOST || defined(__DOXYGEN__) -#define STM32_SYSCLK_MAX STM32_BOOST_SYSCLK_MAX -#define STM32_HSECLK_MAX STM32_BOOST_HSECLK_MAX -#define STM32_HSECLK_BYP_MAX STM32_BOOST_HSECLK_BYP_MAX -#define STM32_HSECLK_MIN STM32_BOOST_HSECLK_MIN -#define STM32_HSECLK_BYP_MIN STM32_BOOST_HSECLK_BYP_MIN -#define STM32_LSECLK_MAX STM32_BOOST_LSECLK_MAX -#define STM32_LSECLK_BYP_MAX STM32_BOOST_LSECLK_BYP_MAX -#define STM32_LSECLK_MIN STM32_BOOST_LSECLK_MIN -#define STM32_LSECLK_BYP_MIN STM32_BOOST_LSECLK_BYP_MIN -#define STM32_PLLIN_MAX STM32_BOOST_PLLIN_MAX -#define STM32_PLLIN_MIN STM32_BOOST_PLLIN_MIN -#define STM32_PLLVCO_MAX STM32_BOOST_PLLVCO_MAX -#define STM32_PLLVCO_MIN STM32_BOOST_PLLVCO_MIN -#define STM32_PLLP_MAX STM32_BOOST_PLLP_MAX -#define STM32_PLLP_MIN STM32_BOOST_PLLP_MIN -#define STM32_PLLQ_MAX STM32_BOOST_PLLQ_MAX -#define STM32_PLLQ_MIN STM32_BOOST_PLLQ_MIN -#define STM32_PLLR_MAX STM32_BOOST_PLLR_MAX -#define STM32_PLLR_MIN STM32_BOOST_PLLR_MIN -#define STM32_PCLK1_MAX STM32_BOOST_PCLK1_MAX -#define STM32_PCLK2_MAX STM32_BOOST_PCLK2_MAX -#define STM32_ADCCLK_MAX STM32_BOOST_ADCCLK_MAX - -#define STM32_0WS_THRESHOLD STM32_BOOST_0WS_THRESHOLD -#define STM32_1WS_THRESHOLD STM32_BOOST_1WS_THRESHOLD -#define STM32_2WS_THRESHOLD STM32_BOOST_2WS_THRESHOLD -#define STM32_3WS_THRESHOLD STM32_BOOST_3WS_THRESHOLD -#define STM32_4WS_THRESHOLD STM32_BOOST_4WS_THRESHOLD -#define STM32_5WS_THRESHOLD STM32_BOOST_5WS_THRESHOLD -#define STM32_6WS_THRESHOLD STM32_BOOST_6WS_THRESHOLD -#define STM32_7WS_THRESHOLD STM32_BOOST_7WS_THRESHOLD -#define STM32_8WS_THRESHOLD STM32_BOOST_8WS_THRESHOLD - -#else /* !STM32_PWR_BOOST */ -#define STM32_SYSCLK_MAX STM32_VOS1_SYSCLK_MAX_NOBOOST -#define STM32_HSECLK_MAX STM32_VOS1_HSECLK_MAX -#define STM32_HSECLK_BYP_MAX STM32_VOS1_HSECLK_BYP_MAX -#define STM32_HSECLK_MIN STM32_VOS1_HSECLK_MIN -#define STM32_HSECLK_BYP_MIN STM32_VOS1_HSECLK_BYP_MIN -#define STM32_LSECLK_MAX STM32_VOS1_LSECLK_MAX -#define STM32_LSECLK_BYP_MAX STM32_VOS1_LSECLK_BYP_MAX -#define STM32_LSECLK_MIN STM32_VOS1_LSECLK_MIN -#define STM32_LSECLK_BYP_MIN STM32_VOS1_LSECLK_BYP_MIN -#define STM32_PLLIN_MAX STM32_VOS1_PLLIN_MAX -#define STM32_PLLIN_MIN STM32_VOS1_PLLIN_MIN -#define STM32_PLLVCO_MAX STM32_VOS1_PLLVCO_MAX -#define STM32_PLLVCO_MIN STM32_VOS1_PLLVCO_MIN -#define STM32_PLLP_MAX STM32_VOS1_PLLP_MAX -#define STM32_PLLP_MIN STM32_VOS1_PLLP_MIN -#define STM32_PLLQ_MAX STM32_VOS1_PLLQ_MAX -#define STM32_PLLQ_MIN STM32_VOS1_PLLQ_MIN -#define STM32_PLLR_MAX STM32_VOS1_PLLR_MAX -#define STM32_PLLR_MIN STM32_VOS1_PLLR_MIN -#define STM32_PCLK1_MAX STM32_VOS1_PCLK1_MAX -#define STM32_PCLK2_MAX STM32_VOS1_PCLK2_MAX -#define STM32_ADCCLK_MAX STM32_VOS1_ADCCLK_MAX - -#define STM32_0WS_THRESHOLD STM32_VOS1_0WS_THRESHOLD -#define STM32_1WS_THRESHOLD STM32_VOS1_1WS_THRESHOLD -#define STM32_2WS_THRESHOLD STM32_VOS1_2WS_THRESHOLD -#define STM32_3WS_THRESHOLD STM32_VOS1_3WS_THRESHOLD -#define STM32_4WS_THRESHOLD STM32_VOS1_4WS_THRESHOLD -#define STM32_5WS_THRESHOLD STM32_VOS1_5WS_THRESHOLD -#define STM32_6WS_THRESHOLD STM32_VOS1_6WS_THRESHOLD -#define STM32_7WS_THRESHOLD STM32_VOS1_7WS_THRESHOLD -#define STM32_8WS_THRESHOLD STM32_VOS1_8WS_THRESHOLD -#endif /* !STM32_PWR_BOOST */ - -#elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX STM32_VOS2_SYSCLK_MAX -#define STM32_SYSCLK_MAX_NOBOOST STM32_VOS2_SYSCLK_MAX_NOBOOST -#define STM32_HSECLK_MAX STM32_VOS2_HSECLK_MAX -#define STM32_HSECLK_BYP_MAX STM32_VOS2_HSECLK_BYP_MAX -#define STM32_HSECLK_MIN STM32_VOS2_HSECLK_MIN -#define STM32_HSECLK_BYP_MIN STM32_VOS2_HSECLK_BYP_MIN -#define STM32_LSECLK_MAX STM32_VOS2_LSECLK_MAX -#define STM32_LSECLK_BYP_MAX STM32_VOS2_LSECLK_BYP_MAX -#define STM32_LSECLK_MIN STM32_VOS2_LSECLK_MIN -#define STM32_LSECLK_BYP_MIN STM32_VOS2_LSECLK_BYP_MIN -#define STM32_PLLIN_MAX STM32_VOS2_PLLIN_MAX -#define STM32_PLLIN_MIN STM32_VOS2_PLLIN_MIN -#define STM32_PLLVCO_MAX STM32_VOS2_PLLVCO_MAX -#define STM32_PLLVCO_MIN STM32_VOS2_PLLVCO_MIN -#define STM32_PLLP_MAX STM32_VOS2_PLLP_MAX -#define STM32_PLLP_MIN STM32_VOS2_PLLP_MIN -#define STM32_PLLQ_MAX STM32_VOS2_PLLQ_MAX -#define STM32_PLLQ_MIN STM32_VOS2_PLLQ_MIN -#define STM32_PLLR_MAX STM32_VOS2_PLLR_MAX -#define STM32_PLLR_MIN STM32_VOS2_PLLR_MIN -#define STM32_PCLK1_MAX STM32_VOS2_PCLK1_MAX -#define STM32_PCLK2_MAX STM32_VOS2_PCLK2_MAX -#define STM32_ADCCLK_MAX STM32_VOS2_ADCCLK_MAX - -#define STM32_0WS_THRESHOLD STM32_VOS2_0WS_THRESHOLD -#define STM32_1WS_THRESHOLD STM32_VOS2_1WS_THRESHOLD -#define STM32_2WS_THRESHOLD STM32_VOS2_2WS_THRESHOLD -#define STM32_3WS_THRESHOLD STM32_VOS2_3WS_THRESHOLD -#define STM32_4WS_THRESHOLD STM32_VOS2_4WS_THRESHOLD -#define STM32_5WS_THRESHOLD STM32_VOS2_5WS_THRESHOLD -#define STM32_6WS_THRESHOLD STM32_VOS2_6WS_THRESHOLD -#define STM32_7WS_THRESHOLD STM32_VOS2_7WS_THRESHOLD -#define STM32_8WS_THRESHOLD STM32_VOS2_8WS_THRESHOLD - -#else -#error "invalid STM32_VOS value specified" -#endif - -/* - * HSI16 related checks. - */ -#if STM32_HSI16_ENABLED -#else /* !STM32_HSI16_ENABLED */ - - #if STM32_SW == STM32_SW_HSI16 - #error "HSI16 not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) - #error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - #if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16)) - #error "HSI16 not enabled, required by STM32_MCOSEL" - #endif - - #if (STM32_USART1SEL == STM32_USART1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_USART1SEL" - #endif - #if (STM32_USART2SEL == STM32_USART2SEL_HSI16) - #error "HSI16 not enabled, required by STM32_USART2SEL" - #endif - #if (STM32_USART3SEL == STM32_USART3SEL_HSI16) - #error "HSI16 not enabled, required by STM32_USART3SEL" - #endif - #if (STM32_UART4SEL == STM32_UART4SEL_HSI16) - #error "HSI16 not enabled, required by STM32_UART4SEL_HSI16" - #endif - #if (STM32_UART5SEL == STM32_UART5SEL_HSI16) - #error "HSI16 not enabled, required by STM32_UART5SEL_HSI16" - #endif - #if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_LPUART1SEL" - #endif - - #if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_I2C1SEL" - #endif - #if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) - #error "HSI16 not enabled, required by STM32_I2C2SEL" - #endif - #if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) - #error "HSI16 not enabled, required by STM32_I2C3SEL" - #endif - #if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) - #error "HSI16 not enabled, required by STM32_I2C4SEL" - #endif - - #if (STM32_SAI1SEL == STM32_SAI1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_SAI1SEL" - #endif - #if (STM32_I2S23SEL == STM32_I2S23SEL_HSI16) - #error "HSI16 not enabled, required by STM32_I2S23SEL" - #endif - - #if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_LPTIM1SEL" - #endif - - #if (STM32_QSPISEL == STM32_QSPISEL_HSI16) - #error "HSI16 not enabled, required by STM32_QSPISEL_HSI16" - #endif - -#endif /* !STM32_HSI16_ENABLED */ - -/* - * HSI48 related checks. - */ -#if STM32_HSI48_ENABLED -#else /* !STM32_HSI48_ENABLED */ - - #if STM32_MCOSEL == STM32_MCOSEL_HSI48 - #error "HSI48 not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 - #error "HSI48 not enabled, required by STM32_CLK48SEL" - #endif - -#endif /* !STM32_HSI48_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#else /* !STM32_HSE_ENABLED */ - - #if STM32_SW == STM32_SW_HSE - #error "HSE not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) - #error "HSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV - #error "HSE not enabled, required by STM32_RTCSEL" - #endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - - #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) - #error "LSI not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSI - #error "LSI not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSI - #error "LSI not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - - #if (STM32_LSECLK == 0) - #error "LSE frequency not defined" - #endif - - #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) - #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" - #endif - -#else /* !STM32_LSE_ENABLED */ - - #if STM32_RTCSEL == STM32_RTCSEL_LSE - #error "LSE not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSE - #error "LSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSE - #error "LSE not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \ - defined(__DOXYGEN__) - #define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) -#else - #error "invalid STM32_PLLM_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) - #define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 - #define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK - #define STM32_PLLCLKIN 0 - -#else - #error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLL input frequency range check. - */ -#if (STM32_PLLCLKIN != 0) && \ - ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) - #error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_SW == STM32_SW_PLLRCLK) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ - (STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK) || \ - (STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK) || \ - (STM32_I2S23SEL == STM32_I2S23SEL_PLLQCLK) || \ - (STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK) || \ - (STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK) || \ - (STM32_QSPISEL == STM32_QSPISEL_PLLQCLK) || \ - defined(__DOXYGEN__) - - #if STM32_PLLCLKIN == 0 - #error "PLL activation required but no PLL clock selected" - #endif - - /** - * @brief PLL activation flag. - */ - #define STM32_ACTIVATE_PLL TRUE -#else - - #define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \ - defined(__DOXYGEN__) - #define STM32_PLLN (STM32_PLLN_VALUE << 8) -#else - #error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) - #define STM32_PLLP (0 << 17) - -#elif STM32_PLLP_VALUE == 17 - #define STM32_PLLP (1 << 17) - -#else - #error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) - #define STM32_PLLQ (0 << 21) - -#elif STM32_PLLQ_VALUE == 4 - #define STM32_PLLQ (1 << 21) - -#elif STM32_PLLQ_VALUE == 6 - #define STM32_PLLQ (2 << 21) - -#elif STM32_PLLQ_VALUE == 8 - #define STM32_PLLQ (3 << 21) - -#else - #error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLR field. - */ -#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) - #define STM32_PLLR (0 << 25) - -#elif STM32_PLLR_VALUE == 4 - #define STM32_PLLR (1 << 25) - -#elif STM32_PLLR_VALUE == 6 - #define STM32_PLLR (2 << 25) - -#elif STM32_PLLR_VALUE == 8 - #define STM32_PLLR (3 << 25) - -#else - #error "invalid STM32_PLLR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLPDIV field. - */ -#if (STM32_PLLPDIV_VALUE == 0) || \ - ((STM32_PLLPDIV_VALUE >= 2) && (STM32_PLLPDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) -#else -#error "invalid STM32_PLLPDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLPEN field. - */ -#if (STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK) || \ - (STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK) || \ - defined(__DOXYGEN__) - #define STM32_PLLPEN (1 << 16) - -#else - #define STM32_PLLPEN (0 << 16) -#endif - -/** - * @brief STM32_PLLQEN field. - */ -#if (STM32_QSPISEL == STM32_QSPISEL_PLLQCLK) || \ - (STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK) || \ - (STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK) || \ - (STM32_I2S23SEL == STM32_I2S23SEL_PLLQCLK) || \ - defined(__DOXYGEN__) - #define STM32_PLLQEN (1 << 20) - -#else - #define STM32_PLLQEN (0 << 20) -#endif - -/** - * @brief STM32_PLLREN field. - */ -#if (STM32_SW == STM32_SW_PLLRCLK) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ - defined(__DOXYGEN__) - #define STM32_PLLREN (1 << 24) - -#else - #define STM32_PLLREN (0 << 24) -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) - #error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL P output clock frequency. - */ -#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) - #define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) -#else - #define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) -#endif - -/** - * @brief PLL Q output clock frequency. - */ -#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) - -/** - * @brief PLL R output clock frequency. - */ -#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) - -/* - * PLL-P output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) - #error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLL-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) - #error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLL-R output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) - #error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) - #define STM32_SYSCLK STM32_HSI16CLK - -#elif (STM32_SW == STM32_SW_HSI16) - #define STM32_SYSCLK STM32_HSI16CLK - -#elif (STM32_SW == STM32_SW_HSE) - #define STM32_SYSCLK STM32_HSECLK - -#elif (STM32_SW == STM32_SW_PLLRCLK) - #define STM32_SYSCLK STM32_PLL_R_CLKOUT - -#else - #error "invalid STM32_SW value specified" -#endif - -/* - * Check on the system clock. - */ -#if STM32_SYSCLK > STM32_SYSCLK_MAX - #error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) - #define STM32_HCLK (STM32_SYSCLK / 1) - -#elif STM32_HPRE == STM32_HPRE_DIV2 - #define STM32_HCLK (STM32_SYSCLK / 2) - -#elif STM32_HPRE == STM32_HPRE_DIV4 - #define STM32_HCLK (STM32_SYSCLK / 4) - -#elif STM32_HPRE == STM32_HPRE_DIV8 - #define STM32_HCLK (STM32_SYSCLK / 8) - -#elif STM32_HPRE == STM32_HPRE_DIV16 - #define STM32_HCLK (STM32_SYSCLK / 16) - -#elif STM32_HPRE == STM32_HPRE_DIV64 - #define STM32_HCLK (STM32_SYSCLK / 64) - -#elif STM32_HPRE == STM32_HPRE_DIV128 - #define STM32_HCLK (STM32_SYSCLK / 128) - -#elif STM32_HPRE == STM32_HPRE_DIV256 - #define STM32_HCLK (STM32_SYSCLK / 256) - -#elif STM32_HPRE == STM32_HPRE_DIV512 - #define STM32_HCLK (STM32_SYSCLK / 512) - -#else - #error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX - #error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) - #define STM32_PCLK1 (STM32_HCLK / 1) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 - #define STM32_PCLK1 (STM32_HCLK / 2) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 - #define STM32_PCLK1 (STM32_HCLK / 4) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 - #define STM32_PCLK1 (STM32_HCLK / 8) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 - #define STM32_PCLK1 (STM32_HCLK / 16) - -#else - #error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) - #define STM32_PCLK2 (STM32_HCLK / 1) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 - #define STM32_PCLK2 (STM32_HCLK / 2) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 - #define STM32_PCLK2 (STM32_HCLK / 4) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 - #define STM32_PCLK2 (STM32_HCLK / 8) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 - #define STM32_PCLK2 (STM32_HCLK / 16) - -#else - #error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief MCO divider clock frequency. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) - #define STM32_MCODIVCLK 0 - -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK - #define STM32_MCODIVCLK STM32_SYSCLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 - #define STM32_MCODIVCLK STM32_HSI16CLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSE - #define STM32_MCODIVCLK STM32_HSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_PLLRCLK - #define STM32_MCODIVCLK STM32_PLL_R_CLKOUT - -#elif STM32_MCOSEL == STM32_MCOSEL_LSI - #define STM32_MCODIVCLK STM32_LSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_LSE - #define STM32_MCODIVCLK STM32_LSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 - #define STM32_MCODIVCLK STM32_HSI48CLK - -#else - #error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock frequency. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) - #define STM32_MCOCLK STM32_MCODIVCLK - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 - #define STM32_MCOCLK (STM32_MCODIVCLK / 2) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 - #define STM32_MCOCLK (STM32_MCODIVCLK / 4) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 - #define STM32_MCOCLK (STM32_MCODIVCLK / 8) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 - #define STM32_MCOCLK (STM32_MCODIVCLK / 16) - -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief RTC clock frequency. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) - #define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE - #define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI - #define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV - #define STM32_RTCCLK (STM32_HSECLK / 32) - -#else - #error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 clock frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) - #define STM32_USART1CLK STM32_PCLK2 - -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK - #define STM32_USART1CLK STM32_SYSCLK - -#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 - #define STM32_USART1CLK STM32_HSI16CLK - -#elif STM32_USART1SEL == STM32_USART1SEL_LSE - #define STM32_USART1CLK STM32_LSECLK - -#else - #error "invalid source selected for USART1 clock" -#endif - - /** - * @brief USART2 clock frequency. - */ - #if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_USART2CLK STM32_PCLK1 - - #elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK - #define STM32_USART2CLK STM32_SYSCLK - - #elif STM32_USART2SEL == STM32_USART2SEL_HSI16 - #define STM32_USART2CLK STM32_HSI16CLK - - #elif STM32_USART2SEL == STM32_USART2SEL_LSE - #define STM32_USART2CLK STM32_LSECLK - - #else - #error "invalid source selected for USART2 clock" - #endif - - /** - * @brief USART3 clock frequency. - */ - #if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_USART3CLK STM32_PCLK1 - - #elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK - #define STM32_USART3CLK STM32_SYSCLK - - #elif STM32_USART3SEL == STM32_USART3SEL_HSI16 - #define STM32_USART3CLK STM32_HSI16CLK - - #elif STM32_USART3SEL == STM32_USART3SEL_LSE - #define STM32_USART3CLK STM32_LSECLK - - #else - #error "invalid source selected for USART3 clock" - #endif - -/** - * @brief UART4 clock frequency. - */ -#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_UART4CLK STM32_PCLK1 - -#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK - #define STM32_UART4CLK STM32_SYSCLK - -#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 - #define STM32_UART4CLK STM32_HSI16CLK - -#elif STM32_UART4SEL == STM32_UART4SEL_LSE - #define STM32_UART4CLK STM32_LSECLK - -#else - #error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 clock frequency. - */ -#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_UART5CLK STM32_PCLK1 - -#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK - #define STM32_UART5CLK STM32_SYSCLK - -#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 - #define STM32_UART5CLK STM32_HSI16CLK - -#elif STM32_UART5SEL == STM32_UART5SEL_LSE - #define STM32_UART5CLK STM32_LSECLK - -#else - #error "invalid source selected for UART5 clock" -#endif - -/** - * @brief LPUART1 clock frequency. - */ -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_LPUART1CLK STM32_PCLK1 - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK - #define STM32_LPUART1CLK STM32_SYSCLK - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 - #define STM32_LPUART1CLK STM32_HSI16CLK - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE - #define STM32_LPUART1CLK STM32_LSECLK - -#else -#error "invalid source selected for LPUART1 clock" -#endif - -/** - * @brief I2C1 clock frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_I2C1CLK STM32_PCLK1 - -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK - #define STM32_I2C1CLK STM32_SYSCLK - -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 - #define STM32_I2C1CLK STM32_HSI16CLK - -#else - #error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 clock frequency. - */ -#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_I2C2CLK STM32_PCLK1 - -#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK - #define STM32_I2C2CLK STM32_SYSCLK - -#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 - #define STM32_I2C2CLK STM32_HSI16CLK - -#else - #error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C3 clock frequency. - */ -#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_I2C3CLK STM32_PCLK1 - -#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK - #define STM32_I2C3CLK STM32_SYSCLK - -#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 - #define STM32_I2C3CLK STM32_HSI16CLK - -#else - #error "invalid source selected for I2C3 clock" -#endif - -/** - * @brief I2C4 clock frequency. - */ -#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_I2C4CLK STM32_PCLK1 - -#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK - #define STM32_I2C4CLK STM32_SYSCLK - -#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 - #define STM32_I2C4CLK STM32_HSI16CLK - -#else - #error "invalid source selected for I2C4 clock" -#endif - -/** - * @brief LPTIM1 clock frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) - #define STM32_LPTIM1CLK STM32_PCLK1 - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI - #define STM32_LPTIM1CLK STM32_LSICLK - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 - #define STM32_LPTIM1CLK STM32_HSI16CLK - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE - #define STM32_LPTIM1CLK STM32_LSECLK - -#else - #error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief SAI1 clock frequency. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_SYSCLK) || defined(__DOXYGEN__) - #define STM32_SAI1CLK STM32_SYSCLK - -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK - #define STM32_SAI1CLK STM32_PLL_Q_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 - #define STM32_SAI1CLK STM32_HSI16CLK - -#elif STM32_SAI1SEL == STM32_SAI1SEL_CKIN - #define STM32_SAI1CLK 0 /* Unknown, would require a board value */ - -#else - #error "invalid source selected for SAI1 clock" -#endif - -/** - * @brief I2S23 clock frequency. - */ -#if (STM32_I2S23SEL == STM32_I2S23SEL_SYSCLK) || defined(__DOXYGEN__) - #define STM32_I2S23CLK STM32_SYSCLK - -#elif STM32_I2S23SEL == STM32_I2S23SEL_PLLPCLK - #define STM32_I2S23CLK STM32_PLL_P_CLKOUT - -#elif STM32_I2S23SEL == STM32_I2S23SEL_HSI16 - #define STM32_I2S23CLK STM32_HSI16CLK - -#elif STM32_I2S23SEL == STM32_I2S23SEL_CKIN - #define STM32_I2S23CLK 0 /* Unknown, would require a board value */ - -#else - #error "invalid source selected for SAI1 clock" -#endif - -/** - * @brief FDCAN clock frequency. - */ -#if (STM32_FDCANSEL == STM32_FDCANSEL_HSE) || defined(__DOXYGEN__) - #define STM32_FDCANCLK STM32_HSECLK - -#elif STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK - #define STM32_FDCANCLK STM32_PLL_Q_CLKOUT - -#elif STM32_FDCANSEL == STM32_FDCANSEL_PCLK1 - #define STM32_FDCANCLK STM32_PCLK1 - -#else - #error "invalid source selected for FDCAN clock" -#endif - -/** - * @brief 48MHz clock frequency. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) - #define STM32_48CLK STM32_HSI48CLK - -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK - #define STM32_48CLK STM32_PLL_Q_CLKOUT - -#else - #error "invalid source selected for 48MHz clock" -#endif - -/** - * @brief ADC clock frequency. - */ -#if (STM32_ADC12SEL == STM32_ADC12SEL_NOCLK) || defined(__DOXYGEN__) - #define STM32_ADC12CLK 0 - -#elif STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK - #define STM32_ADC12CLK STM32_PLL_P_CLKOUT - -#elif STM32_ADC12SEL == STM32_ADC12SEL_SYSCLK - #define STM32_ADC12CLK STM32_SYSCLK - -#else - #error "invalid source selected for ADC clock" -#endif - -/** - * @brief ADC clock frequency. - */ -#if (STM32_ADC345SEL == STM32_ADC345SEL_NOCLK) || defined(__DOXYGEN__) - #define STM32_ADC345CLK 0 - -#elif STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK - #define STM32_ADC345CLK STM32_PLL_P_CLKOUT - -#elif STM32_ADC345SEL == STM32_ADC345SEL_SYSCLK - #define STM32_ADC345CLK STM32_SYSCLK - -#else - #error "invalid source selected for ADC clock" -#endif - -/** - * @brief TIMP1CLK clock frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) - #define STM32_TIMP1CLK (STM32_PCLK1 * 1) -#else - #define STM32_TIMP1CLK (STM32_PCLK1 * 2) -#endif - -/** - * @brief TIMP2CLK clock frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) - #define STM32_TIMP2CLK (STM32_PCLK2 * 1) -#else - #define STM32_TIMP2CLK (STM32_PCLK2 * 2) -#endif - -/** - * @brief Clock of timers connected to APB1. - */ -#define STM32_TIMCLK1 STM32_TIMP1CLK - -/** - * @brief Clock of timers connected to APB2. - */ -#define STM32_TIMCLK2 STM32_TIMP2CLK - -/** - * @brief RNG clock point. - */ -#define STM32_RNGCLK STM32_48CLK - -/** - * @brief USB clock point. - */ -#define STM32_USBCLK STM32_48CLK - -/** - * @brief Voltage boost settings. - */ -#if STM32_PWR_BOOST || defined(__DOXYGEN__) -#define STM32_CR5BITS PWR_CR5_R1MODE -#else -#define STM32_CR5BITS 0U -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) - #define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD - #define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD - #define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_HCLK <= STM32_3WS_THRESHOLD - #define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS - -#elif STM32_HCLK <= STM32_4WS_THRESHOLD - #define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS - -#else - #define STM32_FLASHBITS FLASH_ACR_LATENCY_5WS -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/hal_lld.h + * @brief STM32G4xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32G431xx, STM32G441xx, STM32G471xx. + * - STM32G473xx, STM32G483xx. + * - STM32G474xx, STM32G484xx. + * - STM32GBK1CB. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32G431xx) || defined(STM32G441xx) || defined(STM32G471xx) || \ + defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32G4 Access Line" + +#elif defined(STM32G473xx) +#define PLATFORM_NAME "STM32G4 Performance Line" + +#elif defined(STM32G483xx) +#define PLATFORM_NAME "STM32G4 Performance Line with Crypto" + +#elif defined(STM32G474xx) +#define PLATFORM_NAME "STM32G4 Hi-resolution Line" + +#elif defined(STM32G484xx) +#define PLATFORM_NAME "STM32G4 Hi-resolution Line with Crypto" + +#elif defined(STM32GBK1CB) +#define PLATFORM_NAME "STM32G4 Mystery Line" + +#else +#error "STM32G4 device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32G4XX) || defined(__DOXYGEN__) +#define STM32G4XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSI16CLK 16000000U /**< 16MHz internal clock. */ +#define STM32_HSI48CLK 48000000U /**< 48MHz internal clock. */ +#define STM32_LSICLK 32000U /**< Low speed internal clock. */ +/** @} */ + +/** + * @name VOS field definitions + * @{ + */ +#define STM32_VOS_MASK (3U << 9U) /**< Core voltage mask. */ +#define STM32_VOS_RANGE1 (1U << 9U) /**< Core voltage 1.2 Volts. */ +#define STM32_VOS_RANGE2 (2U << 9U) /**< Core voltage 1.0 Volts. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3U << 0U) /**< SW field mask. */ +#define STM32_SW_HSI16 (1U << 0U) /**< SYSCLK source is HSI16. */ +#define STM32_SW_HSE (2U << 0U) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLLRCLK (3U << 0U) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15U << 4U) /**< HPRE field mask. */ +#define STM32_HPRE_FIELD(n) ((n) << 4U) /**< HPRE field value. */ +#define STM32_HPRE_DIV1 STM32_HPRE_FIELD(0U) +#define STM32_HPRE_DIV2 STM32_HPRE_FIELD(8U) +#define STM32_HPRE_DIV4 STM32_HPRE_FIELD(9U) +#define STM32_HPRE_DIV8 STM32_HPRE_FIELD(10U) +#define STM32_HPRE_DIV16 STM32_HPRE_FIELD(11U) +#define STM32_HPRE_DIV64 STM32_HPRE_FIELD(12U) +#define STM32_HPRE_DIV128 STM32_HPRE_FIELD(13U) +#define STM32_HPRE_DIV256 STM32_HPRE_FIELD(14U) +#define STM32_HPRE_DIV512 STM32_HPRE_FIELD(15U) + +#define STM32_PPRE1_MASK (7U << 8U) /**< PPRE1 field mask. */ +#define STM32_PPRE1_FIELD(n) ((n) << 8U) /**< PPRE1 field value. */ +#define STM32_PPRE1_DIV1 STM32_PPRE1_FIELD(0U) +#define STM32_PPRE1_DIV2 STM32_PPRE1_FIELD(4U) +#define STM32_PPRE1_DIV4 STM32_PPRE1_FIELD(5U) +#define STM32_PPRE1_DIV8 STM32_PPRE1_FIELD(6U) +#define STM32_PPRE1_DIV16 STM32_PPRE1_FIELD(7U) + +#define STM32_PPRE2_MASK (7U << 11U) /**< PPRE2 field mask. */ +#define STM32_PPRE2_FIELD(n) ((n) << 11U) /**< PPRE2 field value. */ +#define STM32_PPRE2_DIV1 STM32_PPRE2_FIELD(0U) +#define STM32_PPRE2_DIV2 STM32_PPRE2_FIELD(4U) +#define STM32_PPRE2_DIV4 STM32_PPRE2_FIELD(5U) +#define STM32_PPRE2_DIV8 STM32_PPRE2_FIELD(6U) +#define STM32_PPRE2_DIV16 STM32_PPRE2_FIELD(7U) + +#define STM32_MCOSEL_MASK (15U << 24U)/**< MCOSEL field mask. */ +#define STM32_MCOSEL_NOCLOCK (0U << 24U) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1U << 24U) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI16 (3U << 24U) /**< HSI16 clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4U << 24U) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLRCLK (5U << 24U) /**< PLLR clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6U << 24U) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7U << 24U) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_HSI48 (8U << 24U) /**< HSI48 clock on MCO pin. */ + +#define STM32_MCOPRE_MASK (7U << 28U) /**< MCOPRE field mask. */ +#define STM32_MCOPRE_FIELD(n) ((n) << 28U)/**< MCOPRE field value */ +#define STM32_MCOPRE_DIV1 STM32_MCOPRE_FIELD(0U) +#define STM32_MCOPRE_DIV2 STM32_MCOPRE_FIELD(1U) +#define STM32_MCOPRE_DIV4 STM32_MCOPRE_FIELD(2U) +#define STM32_MCOPRE_DIV8 STM32_MCOPRE_FIELD(3U) +#define STM32_MCOPRE_DIV16 STM32_MCOPRE_FIELD(4U) +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CCIPR register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3U << 0U) /**< USART1SEL mask. */ +#define STM32_USART1SEL_PCLK2 (0U << 0U) /**< USART1 source is PCLK2. */ +#define STM32_USART1SEL_SYSCLK (1U << 0U) /**< USART1 source is SYSCLK. */ +#define STM32_USART1SEL_HSI16 (2U << 0U) /**< USART1 source is HSI16. */ +#define STM32_USART1SEL_LSE (3U << 0U) /**< USART1 source is LSE. */ + +#define STM32_USART2SEL_MASK (3U << 2U) /**< USART2 mask. */ +#define STM32_USART2SEL_PCLK1 (0U << 2U) /**< USART2 source is PCLK1. */ +#define STM32_USART2SEL_SYSCLK (1U << 2U) /**< USART2 source is SYSCLK. */ +#define STM32_USART2SEL_HSI16 (2U << 2U) /**< USART2 source is HSI16. */ +#define STM32_USART2SEL_LSE (3U << 2U) /**< USART2 source is LSE. */ + +#define STM32_USART3SEL_MASK (3U << 4U) /**< USART3 mask. */ +#define STM32_USART3SEL_PCLK1 (0U << 4U) /**< USART3 source is PCLK1. */ +#define STM32_USART3SEL_SYSCLK (1U << 4U) /**< USART3 source is SYSCLK. */ +#define STM32_USART3SEL_HSI16 (2U << 4U) /**< USART3 source is HSI16. */ +#define STM32_USART3SEL_LSE (3U << 4U) /**< USART3 source is LSE. */ + +#define STM32_UART4SEL_MASK (3U << 6U) /**< UART4 mask. */ +#define STM32_UART4SEL_PCLK1 (0U << 6U) /**< UART4 source is PCLK1. */ +#define STM32_UART4SEL_SYSCLK (1U << 6U) /**< UART4 source is SYSCLK. */ +#define STM32_UART4SEL_HSI16 (2U << 6U) /**< UART4 source is HSI16. */ +#define STM32_UART4SEL_LSE (3U << 6U) /**< UART4 source is LSE. */ + +#define STM32_UART5SEL_MASK (3U << 8U) /**< UART5 mask. */ +#define STM32_UART5SEL_PCLK1 (0U << 8U) /**< UART5 source is PCLK1. */ +#define STM32_UART5SEL_SYSCLK (1U << 8U) /**< UART5 source is SYSCLK. */ +#define STM32_UART5SEL_HSI16 (2U << 8U) /**< UART5 source is HSI16. */ +#define STM32_UART5SEL_LSE (3U << 8U) /**< UART5 source is LSE. */ + +#define STM32_LPUART1SEL_MASK (3U << 10U) /**< LPUART1 mask. */ +#define STM32_LPUART1SEL_PCLK1 (0U << 10U) /**< LPUART1 source is PCLK1. */ +#define STM32_LPUART1SEL_SYSCLK (1U << 10U) /**< LPUART1 source is SYSCLK. */ +#define STM32_LPUART1SEL_HSI16 (2U << 10U) /**< LPUART1 source is HSI16. */ +#define STM32_LPUART1SEL_LSE (3U << 10U) /**< LPUART1 source is LSE. */ + +#define STM32_I2C1SEL_MASK (3U << 12U) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK1 (0U << 12U) /**< I2C1 source is PCLK1. */ +#define STM32_I2C1SEL_SYSCLK (1U << 12U) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI16 (2U << 12U) /**< I2C1 source is HSI16. */ + +#define STM32_I2C2SEL_MASK (3U << 14U) /**< I2C2SEL mask. */ +#define STM32_I2C2SEL_PCLK1 (0U << 14U) /**< I2C2 source is PCLK1. */ +#define STM32_I2C2SEL_SYSCLK (1U << 14U) /**< I2C2 source is SYSCLK. */ +#define STM32_I2C2SEL_HSI16 (2U << 14U) /**< I2C2 source is HSI16. */ + +#define STM32_I2C3SEL_MASK (3U << 16U) /**< I2C3SEL mask. */ +#define STM32_I2C3SEL_PCLK1 (0U << 16U) /**< I2C3 source is PCLK1. */ +#define STM32_I2C3SEL_SYSCLK (1U << 16U) /**< I2C3 source is SYSCLK. */ +#define STM32_I2C3SEL_HSI16 (2U << 16U) /**< I2C3 source is HSI16. */ + +#define STM32_LPTIM1SEL_MASK (3U << 18U) /**< LPTIM1SEL mask. */ +#define STM32_LPTIM1SEL_PCLK1 (0U << 18U) /**< LPTIM1 source is PCLK1. */ +#define STM32_LPTIM1SEL_LSI (1U << 18U) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_HSI16 (2U << 18U) /**< LPTIM1 source is HSI16. */ +#define STM32_LPTIM1SEL_LSE (3U << 18U) /**< LPTIM1 source is LSE. */ + +#define STM32_SAI1SEL_MASK (3U << 20U) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_SYSCLK (0U << 20U) /**< SAI1 source is SYSCLK. */ +#define STM32_SAI1SEL_PLLQCLK (1U << 20U) /**< SAI1 source is PLLQCLK. */ +#define STM32_SAI1SEL_CKIN (2U << 20U) /**< SAI1 source is CKIN. */ +#define STM32_SAI1SEL_HSI16 (3U << 20U) /**< SAI1 source is HSI16. */ + +#define STM32_I2S23SEL_MASK (3U << 22U) /**< I2S23SEL mask. */ +#define STM32_I2S23SEL_SYSCLK (0U << 22U) /**< I2S23 source is SYSCLK. */ +#define STM32_I2S23SEL_PLLQCLK (1U << 22U) /**< I2S23 source is PLLQCLK. */ +#define STM32_I2S23SEL_CKIN (2U << 22U) /**< I2S23 source is CKIN. */ +#define STM32_I2S23SEL_HSI16 (3U << 22U) /**< I2S23 source is HSI16. */ + +#define STM32_FDCANSEL_MASK (3U << 24U) /**< FDCANSEL mask. */ +#define STM32_FDCANSEL_HSE (0U << 24U) /**< FDCAN source is HSE. */ +#define STM32_FDCANSEL_PLLQCLK (1U << 24U) /**< FDCAN source is PLLQCLK. */ +#define STM32_FDCANSEL_PCLK1 (2U << 24U) /**< FDCAN source is PCLK1. */ + +#define STM32_CLK48SEL_MASK (3U << 26U) /**< CLK48SEL mask. */ +#define STM32_CLK48SEL_HSI48 (0U << 26U) /**< CLK48 source is HSI48. */ +#define STM32_CLK48SEL_PLLQCLK (2U << 26U) /**< CLK48 source is PLLQCLK. */ + +#define STM32_ADC12SEL_MASK (3U << 28U) /**< ADC12SEL mask. */ +#define STM32_ADC12SEL_NOCLK (0U << 28U) /**< ADC12 source is none. */ +#define STM32_ADC12SEL_PLLPCLK (1U << 28U) /**< ADC12 source is PLLPCLK. */ +#define STM32_ADC12SEL_SYSCLK (2U << 28U) /**< ADC12 source is SYSCLK. */ + +#define STM32_ADC345SEL_MASK (3U << 30U) /**< ADC345SEL mask. */ +#define STM32_ADC345SEL_NOCLK (0U << 30U) /**< ADC345 source is none. */ +#define STM32_ADC345SEL_PLLPCLK (1U << 30U) /**< ADC345 source is PLLPCLK. */ +#define STM32_ADC345SEL_SYSCLK (2U << 30U) /**< ADC345 source is SYSCLK. */ +/** @} */ + +/** + * @name RCC_CCIPR2 register bits definitions + * @{ + */ +#define STM32_I2C4SEL_MASK (3U << 0U) /**< I2C4SEL mask. */ +#define STM32_I2C4SEL_PCLK1 (0U << 0U) /**< I2C4 source is PCLK1. */ +#define STM32_I2C4SEL_SYSCLK (1U << 0U) /**< I2C4 source is SYSCLK. */ +#define STM32_I2C4SEL_HSI16 (2U << 0U) /**< I2C4 source is HSI16. */ + +#define STM32_QSPISEL_MASK (3U << 20U) /**< QSPISEL mask. */ +#define STM32_QSPISEL_SYSCLK (0U << 20U) /**< QSPI source is SYSCLK. */ +#define STM32_QSPISEL_HSI16 (1U << 20U) /**< QSPI source is HSI16. */ +#define STM32_QSPISEL_PLLQCLK (2U << 20U) /**< QSPI source is PLLQCLK. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3U << 8U) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0U << 8U) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1U << 8U) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2U << 8U) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3U << 8U) /**< RTC source is HSE divided. */ + +#define STM32_LSCOSEL_MASK (3U << 24U) /**< LSCO pin clock source. */ +#define STM32_LSCOSEL_NOCLOCK (0U << 24U) /**< No clock on LSCO pin. */ +#define STM32_LSCOSEL_LSI (1U << 24U) /**< LSI on LSCO pin. */ +#define STM32_LSCOSEL_LSE (3U << 24U) /**< LSE on LSCO pin. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_RANGE1 +#endif + +/** + * @brief Core voltage boost. + * @note The boost can only be used when STM32_VOS==STM32_VOS_RANGE1. + */ +#if !defined(STM32_PWR_BOOST) || defined(__DOXYGEN__) +#define STM32_PWR_BOOST TRUE +#endif + +/** + * @brief PWR CR2 register initialization value. + */ +#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) +#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0) +#endif + +/** + * @brief PWR CR3 register initialization value. + */ +#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__) +#define STM32_PWR_CR3 (PWR_CR3_EIWF) +#endif + +/** + * @brief PWR CR4 register initialization value. + */ +#if !defined(STM32_PWR_CR4) || defined(__DOXYGEN__) +#define STM32_PWR_CR4 (0U) +#endif + +/** + * @brief PWR PUCRA register initialization value. + */ +#if !defined(STM32_PWR_PUCRA) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRA (0U) +#endif + +/** + * @brief PWR PDCRA register initialization value. + */ +#if !defined(STM32_PWR_PDCRA) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRA (0U) +#endif + +/** + * @brief PWR PUCRB register initialization value. + */ +#if !defined(STM32_PWR_PUCRB) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRB (0U) +#endif + +/** + * @brief PWR PDCRB register initialization value. + */ +#if !defined(STM32_PWR_PDCRB) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRB (0U) +#endif + +/** + * @brief PWR PUCRC register initialization value. + */ +#if !defined(STM32_PWR_PUCRC) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRC (0U) +#endif + +/** + * @brief PWR PDCRC register initialization value. + */ +#if !defined(STM32_PWR_PDCRC) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRC (0U) +#endif + +/** + * @brief PWR PUCRD register initialization value. + */ +#if !defined(STM32_PWR_PUCRD) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRD (0U) +#endif + +/** + * @brief PWR PDCRD register initialization value. + */ +#if !defined(STM32_PWR_PDCRD) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRD (0U) +#endif + +/** + * @brief PWR PUCRE register initialization value. + */ +#if !defined(STM32_PWR_PUCRE) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRE (0U) +#endif + +/** + * @brief PWR PDCRE register initialization value. + */ +#if !defined(STM32_PWR_PDCRE) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRE (0U) +#endif + +/** + * @brief PWR PUCRF register initialization value. + */ +#if !defined(STM32_PWR_PUCRF) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRF (0U) +#endif + +/** + * @brief PWR PDCRF register initialization value. + */ +#if !defined(STM32_PWR_PDCRF) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRF (0U) +#endif + +/** + * @brief PWR PUCRG register initialization value. + */ +#if !defined(STM32_PWR_PUCRG) || defined(__DOXYGEN__) +#define STM32_PWR_PUCRG (0U) +#endif + +/** + * @brief PWR PDCRG register initialization value. + */ +#if !defined(STM32_PWR_PDCRG) || defined(__DOXYGEN__) +#define STM32_PWR_PDCRG (0U) +#endif + +/** + * @brief Enables or disables the HSI16 clock source. + */ +#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSI48 clock source. + */ +#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI48_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 170MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLLRCLK +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 170MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 170MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 4 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 8..127. + * @note The default value is calculated for a 170MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 84 +#endif + +/** + * @brief PLLPDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLPDIV_VALUE 0 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 7 +#endif + +/** + * @brief PLLQ divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 8 +#endif + +/** + * @brief PLLR divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 170MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLR_VALUE 2 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 170MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief LSCO clock source. + */ +#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) +#define STM32_UART5SEL STM32_UART5SEL_SYSCLK +#endif + +/** + * @brief LPUART1 clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#endif + +/** + * @brief I2C3 clock source. + */ +#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#endif + +/** + * @brief I2C4 clock source. + */ +#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#endif + +/** + * @brief SAI1 clock source. + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK +#endif + +/** + * @brief I2S23 clock source. + */ +#if !defined(STM32_I2S23SEL) || defined(__DOXYGEN__) +#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK +#endif + +/** + * @brief FDCAN clock source. + */ +#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__) +#define STM32_FDCANSEL STM32_FDCANSEL_HSE +#endif + +/** + * @brief CLK48 clock source. + */ +#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) +#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 +#endif + +/** + * @brief ADC12 clock source. + */ +#if !defined(STM32_ADC12SEL) || defined(__DOXYGEN__) +#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK +#endif + +/** + * @brief ADC34 clock source. + */ +#if !defined(STM32_ADC345SEL) || defined(__DOXYGEN__) +#define STM32_ADC345SEL STM32_ADC345SEL_PLLPCLK +#endif + +/** + * @brief QSPI clock source. + */ +#if !defined(STM32_QSPISEL) || defined(__DOXYGEN__) +#define STM32_QSPISEL STM32_QSPISEL_SYSCLK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Boost mode checks.*/ +#if STM32_PWR_BOOST && (STM32_VOS != STM32_VOS_RANGE1) +#error "STM32_PWR_BOOST requires STM32_VOS_RANGE1" +#endif + +/* + * Configuration-related checks. + */ +#if !defined(STM32G4xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G4xx_MCUCONF not defined" +#endif + +#if defined(STM32G431xx) && !defined(STM32G431_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G431_MCUCONF not defined" + +#elif defined(STM32G441xx) && !defined(STM32G441_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G441_MCUCONF not defined" + +#elif defined(STM32G471xx) && !defined(STM32G471_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G471_MCUCONF not defined" + +#elif defined(STM32G473xx) && !defined(STM32G473_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G473_MCUCONF not defined" + +#elif defined(STM32G483xx) && !defined(STM32G473_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G483_MCUCONF not defined" + +#elif defined(STM32G474xx) && !defined(STM32G474_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G474_MCUCONF not defined" + +#elif defined(STM32G484xx) && !defined(STM32G484_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32G484_MCUCONF not defined" + +#elif defined(STM32GBK1CB) && !defined(STM32GBK1CB_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32GBK1CB_MCUCONF not defined" + +#endif + +/* + * Board files sanity checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif + +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/** + * @name System Limits for VOS range 1 with boost + * @{ + */ +#define STM32_BOOST_SYSCLK_MAX 170000000 +#define STM32_BOOST_HSECLK_MAX 48000000 +#define STM32_BOOST_HSECLK_BYP_MAX 48000000 +#define STM32_BOOST_HSECLK_MIN 8000000 +#define STM32_BOOST_HSECLK_BYP_MIN 8000000 +#define STM32_BOOST_LSECLK_MAX 32768 +#define STM32_BOOST_LSECLK_BYP_MAX 1000000 +#define STM32_BOOST_LSECLK_MIN 32768 +#define STM32_BOOST_LSECLK_BYP_MIN 32768 +#define STM32_BOOST_PLLIN_MAX 16000000 +#define STM32_BOOST_PLLIN_MIN 2660000 +#define STM32_BOOST_PLLVCO_MAX 344000000 +#define STM32_BOOST_PLLVCO_MIN 96000000 +#define STM32_BOOST_PLLP_MAX 170000000 +#define STM32_BOOST_PLLP_MIN 2064500 +#define STM32_BOOST_PLLQ_MAX 170000000 +#define STM32_BOOST_PLLQ_MIN 8000000 +#define STM32_BOOST_PLLR_MAX 170000000 +#define STM32_BOOST_PLLR_MIN 8000000 +#define STM32_BOOST_PCLK1_MAX 170000000 +#define STM32_BOOST_PCLK2_MAX 170000000 +#define STM32_BOOST_ADCCLK_MAX 60000000 + +#define STM32_BOOST_0WS_THRESHOLD 34000000 +#define STM32_BOOST_1WS_THRESHOLD 68000000 +#define STM32_BOOST_2WS_THRESHOLD 102000000 +#define STM32_BOOST_3WS_THRESHOLD 136000000 +#define STM32_BOOST_4WS_THRESHOLD 170000000 +/** @} */ + +/** + * @name System Limits for VOS range 1 without boost + * @{ + */ +#define STM32_VOS1_SYSCLK_MAX 150000000 +#define STM32_VOS1_HSECLK_MAX 48000000 +#define STM32_VOS1_HSECLK_BYP_MAX 48000000 +#define STM32_VOS1_HSECLK_MIN 8000000 +#define STM32_VOS1_HSECLK_BYP_MIN 8000000 +#define STM32_VOS1_LSECLK_MAX 32768 +#define STM32_VOS1_LSECLK_BYP_MAX 1000000 +#define STM32_VOS1_LSECLK_MIN 32768 +#define STM32_VOS1_LSECLK_BYP_MIN 32768 +#define STM32_VOS1_PLLIN_MAX 16000000 +#define STM32_VOS1_PLLIN_MIN 2660000 +#define STM32_VOS1_PLLVCO_MAX 344000000 +#define STM32_VOS1_PLLVCO_MIN 96000000 +#define STM32_VOS1_PLLP_MAX 150000000 +#define STM32_VOS1_PLLP_MIN 2064500 +#define STM32_VOS1_PLLQ_MAX 150000000 +#define STM32_VOS1_PLLQ_MIN 8000000 +#define STM32_VOS1_PLLR_MAX 150000000 +#define STM32_VOS1_PLLR_MIN 8000000 +#define STM32_VOS1_PCLK1_MAX 150000000 +#define STM32_VOS1_PCLK2_MAX 150000000 +#define STM32_VOS1_ADCCLK_MAX 60000000 + +#define STM32_VOS1_0WS_THRESHOLD 30000000 +#define STM32_VOS1_1WS_THRESHOLD 60000000 +#define STM32_VOS1_2WS_THRESHOLD 90000000 +#define STM32_VOS1_3WS_THRESHOLD 120000000 +#define STM32_VOS1_4WS_THRESHOLD 150000000 +/** @} */ + +/** + * @name System Limits for VOS range 2 + * @{ + */ +#define STM32_VOS2_SYSCLK_MAX 26000000 +#define STM32_VOS2_HSECLK_MAX 26000000 +#define STM32_VOS2_HSECLK_BYP_MAX 26000000 +#define STM32_VOS2_HSECLK_MIN 8000000 +#define STM32_VOS2_HSECLK_BYP_MIN 8000000 +#define STM32_VOS2_LSECLK_MAX 32768 +#define STM32_VOS2_LSECLK_BYP_MAX 1000000 +#define STM32_VOS2_LSECLK_MIN 32768 +#define STM32_VOS2_LSECLK_BYP_MIN 32768 +#define STM32_VOS2_PLLIN_MAX 16000000 +#define STM32_VOS2_PLLIN_MIN 2660000 +#define STM32_VOS2_PLLVCO_MAX 128000000 +#define STM32_VOS2_PLLVCO_MIN 96000000 +#define STM32_VOS2_PLLP_MAX 26000000 +#define STM32_VOS2_PLLP_MIN 2064500 +#define STM32_VOS2_PLLQ_MAX 26000000 +#define STM32_VOS2_PLLQ_MIN 8000000 +#define STM32_VOS2_PLLR_MAX 26000000 +#define STM32_VOS2_PLLR_MIN 8000000 +#define STM32_VOS2_PCLK1_MAX 26000000 +#define STM32_VOS2_PCLK2_MAX 26000000 +#define STM32_VOS2_ADCCLK_MAX 26000000 + +#define STM32_VOS2_0WS_THRESHOLD 12000000 +#define STM32_VOS2_1WS_THRESHOLD 24000000 +#define STM32_VOS2_2WS_THRESHOLD 26000000 +#define STM32_VOS2_3WS_THRESHOLD 0 +#define STM32_VOS2_4WS_THRESHOLD 0 +/** @} */ + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) +#if STM32_PWR_BOOST || defined(__DOXYGEN__) +#define STM32_SYSCLK_MAX STM32_BOOST_SYSCLK_MAX +#define STM32_HSECLK_MAX STM32_BOOST_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_BOOST_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_BOOST_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_BOOST_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_BOOST_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_BOOST_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_BOOST_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_BOOST_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_BOOST_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_BOOST_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_BOOST_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_BOOST_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_BOOST_PLLP_MAX +#define STM32_PLLP_MIN STM32_BOOST_PLLP_MIN +#define STM32_PLLQ_MAX STM32_BOOST_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_BOOST_PLLQ_MIN +#define STM32_PLLR_MAX STM32_BOOST_PLLR_MAX +#define STM32_PLLR_MIN STM32_BOOST_PLLR_MIN +#define STM32_PCLK1_MAX STM32_BOOST_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_BOOST_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_BOOST_ADCCLK_MAX + +#define STM32_0WS_THRESHOLD STM32_BOOST_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_BOOST_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_BOOST_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_BOOST_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_BOOST_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_BOOST_5WS_THRESHOLD +#define STM32_6WS_THRESHOLD STM32_BOOST_6WS_THRESHOLD +#define STM32_7WS_THRESHOLD STM32_BOOST_7WS_THRESHOLD +#define STM32_8WS_THRESHOLD STM32_BOOST_8WS_THRESHOLD + +#else /* !STM32_PWR_BOOST */ +#define STM32_SYSCLK_MAX STM32_VOS1_SYSCLK_MAX_NOBOOST +#define STM32_HSECLK_MAX STM32_VOS1_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_VOS1_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_VOS1_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_VOS1_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_VOS1_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_VOS1_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_VOS1_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_VOS1_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_VOS1_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_VOS1_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_VOS1_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_VOS1_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_VOS1_PLLP_MAX +#define STM32_PLLP_MIN STM32_VOS1_PLLP_MIN +#define STM32_PLLQ_MAX STM32_VOS1_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_VOS1_PLLQ_MIN +#define STM32_PLLR_MAX STM32_VOS1_PLLR_MAX +#define STM32_PLLR_MIN STM32_VOS1_PLLR_MIN +#define STM32_PCLK1_MAX STM32_VOS1_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_VOS1_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_VOS1_ADCCLK_MAX + +#define STM32_0WS_THRESHOLD STM32_VOS1_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS1_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS1_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_VOS1_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_VOS1_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_VOS1_5WS_THRESHOLD +#define STM32_6WS_THRESHOLD STM32_VOS1_6WS_THRESHOLD +#define STM32_7WS_THRESHOLD STM32_VOS1_7WS_THRESHOLD +#define STM32_8WS_THRESHOLD STM32_VOS1_8WS_THRESHOLD +#endif /* !STM32_PWR_BOOST */ + +#elif STM32_VOS == STM32_VOS_RANGE2 +#define STM32_SYSCLK_MAX STM32_VOS2_SYSCLK_MAX +#define STM32_SYSCLK_MAX_NOBOOST STM32_VOS2_SYSCLK_MAX_NOBOOST +#define STM32_HSECLK_MAX STM32_VOS2_HSECLK_MAX +#define STM32_HSECLK_BYP_MAX STM32_VOS2_HSECLK_BYP_MAX +#define STM32_HSECLK_MIN STM32_VOS2_HSECLK_MIN +#define STM32_HSECLK_BYP_MIN STM32_VOS2_HSECLK_BYP_MIN +#define STM32_LSECLK_MAX STM32_VOS2_LSECLK_MAX +#define STM32_LSECLK_BYP_MAX STM32_VOS2_LSECLK_BYP_MAX +#define STM32_LSECLK_MIN STM32_VOS2_LSECLK_MIN +#define STM32_LSECLK_BYP_MIN STM32_VOS2_LSECLK_BYP_MIN +#define STM32_PLLIN_MAX STM32_VOS2_PLLIN_MAX +#define STM32_PLLIN_MIN STM32_VOS2_PLLIN_MIN +#define STM32_PLLVCO_MAX STM32_VOS2_PLLVCO_MAX +#define STM32_PLLVCO_MIN STM32_VOS2_PLLVCO_MIN +#define STM32_PLLP_MAX STM32_VOS2_PLLP_MAX +#define STM32_PLLP_MIN STM32_VOS2_PLLP_MIN +#define STM32_PLLQ_MAX STM32_VOS2_PLLQ_MAX +#define STM32_PLLQ_MIN STM32_VOS2_PLLQ_MIN +#define STM32_PLLR_MAX STM32_VOS2_PLLR_MAX +#define STM32_PLLR_MIN STM32_VOS2_PLLR_MIN +#define STM32_PCLK1_MAX STM32_VOS2_PCLK1_MAX +#define STM32_PCLK2_MAX STM32_VOS2_PCLK2_MAX +#define STM32_ADCCLK_MAX STM32_VOS2_ADCCLK_MAX + +#define STM32_0WS_THRESHOLD STM32_VOS2_0WS_THRESHOLD +#define STM32_1WS_THRESHOLD STM32_VOS2_1WS_THRESHOLD +#define STM32_2WS_THRESHOLD STM32_VOS2_2WS_THRESHOLD +#define STM32_3WS_THRESHOLD STM32_VOS2_3WS_THRESHOLD +#define STM32_4WS_THRESHOLD STM32_VOS2_4WS_THRESHOLD +#define STM32_5WS_THRESHOLD STM32_VOS2_5WS_THRESHOLD +#define STM32_6WS_THRESHOLD STM32_VOS2_6WS_THRESHOLD +#define STM32_7WS_THRESHOLD STM32_VOS2_7WS_THRESHOLD +#define STM32_8WS_THRESHOLD STM32_VOS2_8WS_THRESHOLD + +#else +#error "invalid STM32_VOS value specified" +#endif + +/* + * HSI16 related checks. + */ +#if STM32_HSI16_ENABLED +#else /* !STM32_HSI16_ENABLED */ + + #if STM32_SW == STM32_SW_HSI16 + #error "HSI16 not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) + #error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + #if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16)) + #error "HSI16 not enabled, required by STM32_MCOSEL" + #endif + + #if (STM32_USART1SEL == STM32_USART1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_USART1SEL" + #endif + #if (STM32_USART2SEL == STM32_USART2SEL_HSI16) + #error "HSI16 not enabled, required by STM32_USART2SEL" + #endif + #if (STM32_USART3SEL == STM32_USART3SEL_HSI16) + #error "HSI16 not enabled, required by STM32_USART3SEL" + #endif + #if (STM32_UART4SEL == STM32_UART4SEL_HSI16) + #error "HSI16 not enabled, required by STM32_UART4SEL_HSI16" + #endif + #if (STM32_UART5SEL == STM32_UART5SEL_HSI16) + #error "HSI16 not enabled, required by STM32_UART5SEL_HSI16" + #endif + #if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_LPUART1SEL" + #endif + + #if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_I2C1SEL" + #endif + #if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) + #error "HSI16 not enabled, required by STM32_I2C2SEL" + #endif + #if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) + #error "HSI16 not enabled, required by STM32_I2C3SEL" + #endif + #if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) + #error "HSI16 not enabled, required by STM32_I2C4SEL" + #endif + + #if (STM32_SAI1SEL == STM32_SAI1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_SAI1SEL" + #endif + #if (STM32_I2S23SEL == STM32_I2S23SEL_HSI16) + #error "HSI16 not enabled, required by STM32_I2S23SEL" + #endif + + #if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_LPTIM1SEL" + #endif + + #if (STM32_QSPISEL == STM32_QSPISEL_HSI16) + #error "HSI16 not enabled, required by STM32_QSPISEL_HSI16" + #endif + +#endif /* !STM32_HSI16_ENABLED */ + +/* + * HSI48 related checks. + */ +#if STM32_HSI48_ENABLED +#else /* !STM32_HSI48_ENABLED */ + + #if STM32_MCOSEL == STM32_MCOSEL_HSI48 + #error "HSI48 not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 + #error "HSI48 not enabled, required by STM32_CLK48SEL" + #endif + +#endif /* !STM32_HSI48_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#else /* !STM32_HSE_ENABLED */ + + #if STM32_SW == STM32_SW_HSE + #error "HSE not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) + #error "HSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV + #error "HSE not enabled, required by STM32_RTCSEL" + #endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + + #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) + #error "LSI not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSI + #error "LSI not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSI + #error "LSI not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + + #if (STM32_LSECLK == 0) + #error "LSE frequency not defined" + #endif + + #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) + #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" + #endif + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) + #error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" + #endif + +#else /* !STM32_LSE_ENABLED */ + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) + #error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_LSE + #error "LSE not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSE + #error "LSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSE + #error "LSE not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \ + defined(__DOXYGEN__) + #define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) +#else + #error "invalid STM32_PLLM_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) + #define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 + #define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK + #define STM32_PLLCLKIN 0 + +#else + #error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLL input frequency range check. + */ +#if (STM32_PLLCLKIN != 0) && \ + ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) + #error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_SW == STM32_SW_PLLRCLK) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ + (STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK) || \ + (STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK) || \ + (STM32_I2S23SEL == STM32_I2S23SEL_PLLQCLK) || \ + (STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK) || \ + (STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK) || \ + (STM32_QSPISEL == STM32_QSPISEL_PLLQCLK) || \ + defined(__DOXYGEN__) + + #if STM32_PLLCLKIN == 0 + #error "PLL activation required but no PLL clock selected" + #endif + + /** + * @brief PLL activation flag. + */ + #define STM32_ACTIVATE_PLL TRUE +#else + + #define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \ + defined(__DOXYGEN__) + #define STM32_PLLN (STM32_PLLN_VALUE << 8) +#else + #error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) + #define STM32_PLLP (0 << 17) + +#elif STM32_PLLP_VALUE == 17 + #define STM32_PLLP (1 << 17) + +#else + #error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) + #define STM32_PLLQ (0 << 21) + +#elif STM32_PLLQ_VALUE == 4 + #define STM32_PLLQ (1 << 21) + +#elif STM32_PLLQ_VALUE == 6 + #define STM32_PLLQ (2 << 21) + +#elif STM32_PLLQ_VALUE == 8 + #define STM32_PLLQ (3 << 21) + +#else + #error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLR field. + */ +#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) + #define STM32_PLLR (0 << 25) + +#elif STM32_PLLR_VALUE == 4 + #define STM32_PLLR (1 << 25) + +#elif STM32_PLLR_VALUE == 6 + #define STM32_PLLR (2 << 25) + +#elif STM32_PLLR_VALUE == 8 + #define STM32_PLLR (3 << 25) + +#else + #error "invalid STM32_PLLR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLPDIV field. + */ +#if (STM32_PLLPDIV_VALUE == 0) || \ + ((STM32_PLLPDIV_VALUE >= 2) && (STM32_PLLPDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) +#else +#error "invalid STM32_PLLPDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLPEN field. + */ +#if (STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK) || \ + (STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK) || \ + defined(__DOXYGEN__) + #define STM32_PLLPEN (1 << 16) + +#else + #define STM32_PLLPEN (0 << 16) +#endif + +/** + * @brief STM32_PLLQEN field. + */ +#if (STM32_QSPISEL == STM32_QSPISEL_PLLQCLK) || \ + (STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK) || \ + (STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK) || \ + (STM32_I2S23SEL == STM32_I2S23SEL_PLLQCLK) || \ + defined(__DOXYGEN__) + #define STM32_PLLQEN (1 << 20) + +#else + #define STM32_PLLQEN (0 << 20) +#endif + +/** + * @brief STM32_PLLREN field. + */ +#if (STM32_SW == STM32_SW_PLLRCLK) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \ + defined(__DOXYGEN__) + #define STM32_PLLREN (1 << 24) + +#else + #define STM32_PLLREN (0 << 24) +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) + #error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL P output clock frequency. + */ +#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) + #define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) +#else + #define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) +#endif + +/** + * @brief PLL Q output clock frequency. + */ +#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) + +/** + * @brief PLL R output clock frequency. + */ +#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) + +/* + * PLL-P output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) + #error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLL-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) + #error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLL-R output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) + #error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) + #define STM32_SYSCLK STM32_HSI16CLK + +#elif (STM32_SW == STM32_SW_HSI16) + #define STM32_SYSCLK STM32_HSI16CLK + +#elif (STM32_SW == STM32_SW_HSE) + #define STM32_SYSCLK STM32_HSECLK + +#elif (STM32_SW == STM32_SW_PLLRCLK) + #define STM32_SYSCLK STM32_PLL_R_CLKOUT + +#else + #error "invalid STM32_SW value specified" +#endif + +/* + * Check on the system clock. + */ +#if STM32_SYSCLK > STM32_SYSCLK_MAX + #error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) + #define STM32_HCLK (STM32_SYSCLK / 1) + +#elif STM32_HPRE == STM32_HPRE_DIV2 + #define STM32_HCLK (STM32_SYSCLK / 2) + +#elif STM32_HPRE == STM32_HPRE_DIV4 + #define STM32_HCLK (STM32_SYSCLK / 4) + +#elif STM32_HPRE == STM32_HPRE_DIV8 + #define STM32_HCLK (STM32_SYSCLK / 8) + +#elif STM32_HPRE == STM32_HPRE_DIV16 + #define STM32_HCLK (STM32_SYSCLK / 16) + +#elif STM32_HPRE == STM32_HPRE_DIV64 + #define STM32_HCLK (STM32_SYSCLK / 64) + +#elif STM32_HPRE == STM32_HPRE_DIV128 + #define STM32_HCLK (STM32_SYSCLK / 128) + +#elif STM32_HPRE == STM32_HPRE_DIV256 + #define STM32_HCLK (STM32_SYSCLK / 256) + +#elif STM32_HPRE == STM32_HPRE_DIV512 + #define STM32_HCLK (STM32_SYSCLK / 512) + +#else + #error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX + #error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) + #define STM32_PCLK1 (STM32_HCLK / 1) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 + #define STM32_PCLK1 (STM32_HCLK / 2) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 + #define STM32_PCLK1 (STM32_HCLK / 4) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 + #define STM32_PCLK1 (STM32_HCLK / 8) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 + #define STM32_PCLK1 (STM32_HCLK / 16) + +#else + #error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) + #define STM32_PCLK2 (STM32_HCLK / 1) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 + #define STM32_PCLK2 (STM32_HCLK / 2) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 + #define STM32_PCLK2 (STM32_HCLK / 4) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 + #define STM32_PCLK2 (STM32_HCLK / 8) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 + #define STM32_PCLK2 (STM32_HCLK / 16) + +#else + #error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief MCO divider clock frequency. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) + #define STM32_MCODIVCLK 0 + +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK + #define STM32_MCODIVCLK STM32_SYSCLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 + #define STM32_MCODIVCLK STM32_HSI16CLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSE + #define STM32_MCODIVCLK STM32_HSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_PLLRCLK + #define STM32_MCODIVCLK STM32_PLL_R_CLKOUT + +#elif STM32_MCOSEL == STM32_MCOSEL_LSI + #define STM32_MCODIVCLK STM32_LSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_LSE + #define STM32_MCODIVCLK STM32_LSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 + #define STM32_MCODIVCLK STM32_HSI48CLK + +#else + #error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock frequency. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) + #define STM32_MCOCLK STM32_MCODIVCLK + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 + #define STM32_MCOCLK (STM32_MCODIVCLK / 2) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 + #define STM32_MCOCLK (STM32_MCODIVCLK / 4) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 + #define STM32_MCOCLK (STM32_MCODIVCLK / 8) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 + #define STM32_MCOCLK (STM32_MCODIVCLK / 16) + +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief RTC clock frequency. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) + #define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE + #define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI + #define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV + #define STM32_RTCCLK (STM32_HSECLK / 32) + +#else + #error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 clock frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) + #define STM32_USART1CLK STM32_PCLK2 + +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK + #define STM32_USART1CLK STM32_SYSCLK + +#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 + #define STM32_USART1CLK STM32_HSI16CLK + +#elif STM32_USART1SEL == STM32_USART1SEL_LSE + #define STM32_USART1CLK STM32_LSECLK + +#else + #error "invalid source selected for USART1 clock" +#endif + + /** + * @brief USART2 clock frequency. + */ + #if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_USART2CLK STM32_PCLK1 + + #elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK + #define STM32_USART2CLK STM32_SYSCLK + + #elif STM32_USART2SEL == STM32_USART2SEL_HSI16 + #define STM32_USART2CLK STM32_HSI16CLK + + #elif STM32_USART2SEL == STM32_USART2SEL_LSE + #define STM32_USART2CLK STM32_LSECLK + + #else + #error "invalid source selected for USART2 clock" + #endif + + /** + * @brief USART3 clock frequency. + */ + #if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_USART3CLK STM32_PCLK1 + + #elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK + #define STM32_USART3CLK STM32_SYSCLK + + #elif STM32_USART3SEL == STM32_USART3SEL_HSI16 + #define STM32_USART3CLK STM32_HSI16CLK + + #elif STM32_USART3SEL == STM32_USART3SEL_LSE + #define STM32_USART3CLK STM32_LSECLK + + #else + #error "invalid source selected for USART3 clock" + #endif + +/** + * @brief UART4 clock frequency. + */ +#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_UART4CLK STM32_PCLK1 + +#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK + #define STM32_UART4CLK STM32_SYSCLK + +#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 + #define STM32_UART4CLK STM32_HSI16CLK + +#elif STM32_UART4SEL == STM32_UART4SEL_LSE + #define STM32_UART4CLK STM32_LSECLK + +#else + #error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 clock frequency. + */ +#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_UART5CLK STM32_PCLK1 + +#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK + #define STM32_UART5CLK STM32_SYSCLK + +#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 + #define STM32_UART5CLK STM32_HSI16CLK + +#elif STM32_UART5SEL == STM32_UART5SEL_LSE + #define STM32_UART5CLK STM32_LSECLK + +#else + #error "invalid source selected for UART5 clock" +#endif + +/** + * @brief LPUART1 clock frequency. + */ +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_LPUART1CLK STM32_PCLK1 + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK + #define STM32_LPUART1CLK STM32_SYSCLK + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 + #define STM32_LPUART1CLK STM32_HSI16CLK + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE + #define STM32_LPUART1CLK STM32_LSECLK + +#else +#error "invalid source selected for LPUART1 clock" +#endif + +/** + * @brief I2C1 clock frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_I2C1CLK STM32_PCLK1 + +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK + #define STM32_I2C1CLK STM32_SYSCLK + +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 + #define STM32_I2C1CLK STM32_HSI16CLK + +#else + #error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 clock frequency. + */ +#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_I2C2CLK STM32_PCLK1 + +#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK + #define STM32_I2C2CLK STM32_SYSCLK + +#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 + #define STM32_I2C2CLK STM32_HSI16CLK + +#else + #error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C3 clock frequency. + */ +#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_I2C3CLK STM32_PCLK1 + +#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK + #define STM32_I2C3CLK STM32_SYSCLK + +#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 + #define STM32_I2C3CLK STM32_HSI16CLK + +#else + #error "invalid source selected for I2C3 clock" +#endif + +/** + * @brief I2C4 clock frequency. + */ +#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_I2C4CLK STM32_PCLK1 + +#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK + #define STM32_I2C4CLK STM32_SYSCLK + +#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 + #define STM32_I2C4CLK STM32_HSI16CLK + +#else + #error "invalid source selected for I2C4 clock" +#endif + +/** + * @brief LPTIM1 clock frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) + #define STM32_LPTIM1CLK STM32_PCLK1 + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI + #define STM32_LPTIM1CLK STM32_LSICLK + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 + #define STM32_LPTIM1CLK STM32_HSI16CLK + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE + #define STM32_LPTIM1CLK STM32_LSECLK + +#else + #error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief SAI1 clock frequency. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_SYSCLK) || defined(__DOXYGEN__) + #define STM32_SAI1CLK STM32_SYSCLK + +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK + #define STM32_SAI1CLK STM32_PLL_Q_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 + #define STM32_SAI1CLK STM32_HSI16CLK + +#elif STM32_SAI1SEL == STM32_SAI1SEL_CKIN + #define STM32_SAI1CLK 0 /* Unknown, would require a board value */ + +#else + #error "invalid source selected for SAI1 clock" +#endif + +/** + * @brief I2S23 clock frequency. + */ +#if (STM32_I2S23SEL == STM32_I2S23SEL_SYSCLK) || defined(__DOXYGEN__) + #define STM32_I2S23CLK STM32_SYSCLK + +#elif STM32_I2S23SEL == STM32_I2S23SEL_PLLPCLK + #define STM32_I2S23CLK STM32_PLL_P_CLKOUT + +#elif STM32_I2S23SEL == STM32_I2S23SEL_HSI16 + #define STM32_I2S23CLK STM32_HSI16CLK + +#elif STM32_I2S23SEL == STM32_I2S23SEL_CKIN + #define STM32_I2S23CLK 0 /* Unknown, would require a board value */ + +#else + #error "invalid source selected for SAI1 clock" +#endif + +/** + * @brief FDCAN clock frequency. + */ +#if (STM32_FDCANSEL == STM32_FDCANSEL_HSE) || defined(__DOXYGEN__) + #define STM32_FDCANCLK STM32_HSECLK + +#elif STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK + #define STM32_FDCANCLK STM32_PLL_Q_CLKOUT + +#elif STM32_FDCANSEL == STM32_FDCANSEL_PCLK1 + #define STM32_FDCANCLK STM32_PCLK1 + +#else + #error "invalid source selected for FDCAN clock" +#endif + +/** + * @brief 48MHz clock frequency. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) + #define STM32_48CLK STM32_HSI48CLK + +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK + #define STM32_48CLK STM32_PLL_Q_CLKOUT + +#else + #error "invalid source selected for 48MHz clock" +#endif + +/** + * @brief ADC clock frequency. + */ +#if (STM32_ADC12SEL == STM32_ADC12SEL_NOCLK) || defined(__DOXYGEN__) + #define STM32_ADC12CLK 0 + +#elif STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK + #define STM32_ADC12CLK STM32_PLL_P_CLKOUT + +#elif STM32_ADC12SEL == STM32_ADC12SEL_SYSCLK + #define STM32_ADC12CLK STM32_SYSCLK + +#else + #error "invalid source selected for ADC clock" +#endif + +/** + * @brief ADC clock frequency. + */ +#if (STM32_ADC345SEL == STM32_ADC345SEL_NOCLK) || defined(__DOXYGEN__) + #define STM32_ADC345CLK 0 + +#elif STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK + #define STM32_ADC345CLK STM32_PLL_P_CLKOUT + +#elif STM32_ADC345SEL == STM32_ADC345SEL_SYSCLK + #define STM32_ADC345CLK STM32_SYSCLK + +#else + #error "invalid source selected for ADC clock" +#endif + +/** + * @brief TIMP1CLK clock frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) + #define STM32_TIMP1CLK (STM32_PCLK1 * 1) +#else + #define STM32_TIMP1CLK (STM32_PCLK1 * 2) +#endif + +/** + * @brief TIMP2CLK clock frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) + #define STM32_TIMP2CLK (STM32_PCLK2 * 1) +#else + #define STM32_TIMP2CLK (STM32_PCLK2 * 2) +#endif + +/** + * @brief Clock of timers connected to APB1. + */ +#define STM32_TIMCLK1 STM32_TIMP1CLK + +/** + * @brief Clock of timers connected to APB2. + */ +#define STM32_TIMCLK2 STM32_TIMP2CLK + +/** + * @brief RNG clock point. + */ +#define STM32_RNGCLK STM32_48CLK + +/** + * @brief USB clock point. + */ +#define STM32_USBCLK STM32_48CLK + +/** + * @brief Voltage boost settings. + */ +#if STM32_PWR_BOOST || defined(__DOXYGEN__) +#define STM32_CR5BITS PWR_CR5_R1MODE +#else +#define STM32_CR5BITS 0U +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) + #define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD + #define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD + #define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_HCLK <= STM32_3WS_THRESHOLD + #define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS + +#elif STM32_HCLK <= STM32_4WS_THRESHOLD + #define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS + +#else + #define STM32_FLASHBITS FLASH_ACR_LATENCY_5WS +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/platform.mk b/os/hal/ports/STM32/STM32G4xx/platform.mk index f1d83a141f..4b3b0db196 100644 --- a/os/hal/ports/STM32/STM32G4xx/platform.mk +++ b/os/hal/ports/STM32/STM32G4xx/platform.mk @@ -1,46 +1,46 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h b/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h index f4aec572a0..c8a0ed320e 100644 --- a/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h +++ b/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h @@ -1,183 +1,183 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/stm32_dmamux.h - * @brief STM32G4xx DMAMUX handler header. - * - * @addtogroup STM32G4xx_DMAMUX - * @{ - */ - -#ifndef STM32_DMAMUX_H -#define STM32_DMAMUX_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name DMAMUX1 request sources - * @{ - */ -#define STM32_DMAMUX1_REQ_GEN0 1 -#define STM32_DMAMUX1_REQ_GEN1 2 -#define STM32_DMAMUX1_REQ_GEN2 3 -#define STM32_DMAMUX1_REQ_GEN3 4 -#define STM32_DMAMUX1_ADC1 5 -#define STM32_DMAMUX1_DAC1_CH1 6 -#define STM32_DMAMUX1_DAC1_CH2 7 -#define STM32_DMAMUX1_TIM6_UP 8 -#define STM32_DMAMUX1_TIM7_UP 9 -#define STM32_DMAMUX1_SPI1_RX 10 -#define STM32_DMAMUX1_SPI1_TX 11 -#define STM32_DMAMUX1_SPI2_RX 12 -#define STM32_DMAMUX1_SPI2_TX 13 -#define STM32_DMAMUX1_SPI3_RX 14 -#define STM32_DMAMUX1_SPI3_TX 15 -#define STM32_DMAMUX1_I2C1_RX 16 -#define STM32_DMAMUX1_I2C1_TX 17 -#define STM32_DMAMUX1_I2C2_RX 18 -#define STM32_DMAMUX1_I2C2_TX 19 -#define STM32_DMAMUX1_I2C3_RX 20 -#define STM32_DMAMUX1_I2C3_TX 21 -#define STM32_DMAMUX1_I2C4_RX 22 -#define STM32_DMAMUX1_I2C4_TX 23 -#define STM32_DMAMUX1_USART1_RX 24 -#define STM32_DMAMUX1_USART1_TX 25 -#define STM32_DMAMUX1_USART2_RX 26 -#define STM32_DMAMUX1_USART2_TX 27 -#define STM32_DMAMUX1_USART3_RX 28 -#define STM32_DMAMUX1_USART3_TX 29 -#define STM32_DMAMUX1_UART4_RX 30 -#define STM32_DMAMUX1_UART4_TX 31 -#define STM32_DMAMUX1_UART5_RX 32 -#define STM32_DMAMUX1_UART5_TX 33 -#define STM32_DMAMUX1_LPUART1_RX 34 -#define STM32_DMAMUX1_LPUART1_TX 35 -#define STM32_DMAMUX1_ADC2 36 -#define STM32_DMAMUX1_ADC3 37 -#define STM32_DMAMUX1_ADC4 38 -#define STM32_DMAMUX1_ADC5 39 -#define STM32_DMAMUX1_QUADSPI 40 -#define STM32_DMAMUX1_DAC2_CH1 41 -#define STM32_DMAMUX1_TIM1_CH1 42 -#define STM32_DMAMUX1_TIM1_CH2 43 -#define STM32_DMAMUX1_TIM1_CH3 44 -#define STM32_DMAMUX1_TIM1_CH4 45 -#define STM32_DMAMUX1_TIM1_UP 46 -#define STM32_DMAMUX1_TIM1_TRIG 47 -#define STM32_DMAMUX1_TIM1_COM 48 -#define STM32_DMAMUX1_TIM8_CH1 49 -#define STM32_DMAMUX1_TIM8_CH2 50 -#define STM32_DMAMUX1_TIM8_CH3 51 -#define STM32_DMAMUX1_TIM8_CH4 52 -#define STM32_DMAMUX1_TIM8_UP 53 -#define STM32_DMAMUX1_TIM8_TRIG 54 -#define STM32_DMAMUX1_TIM8_COM 55 -#define STM32_DMAMUX1_TIM2_CH1 56 -#define STM32_DMAMUX1_TIM2_CH2 57 -#define STM32_DMAMUX1_TIM2_CH3 58 -#define STM32_DMAMUX1_TIM2_CH4 59 -#define STM32_DMAMUX1_TIM2_UP 60 -#define STM32_DMAMUX1_TIM3_CH1 61 -#define STM32_DMAMUX1_TIM3_CH2 62 -#define STM32_DMAMUX1_TIM3_CH3 63 -#define STM32_DMAMUX1_TIM3_CH4 64 -#define STM32_DMAMUX1_TIM3_UP 65 -#define STM32_DMAMUX1_TIM3_TRIG 66 -#define STM32_DMAMUX1_TIM4_CH1 67 -#define STM32_DMAMUX1_TIM4_CH2 68 -#define STM32_DMAMUX1_TIM4_CH3 69 -#define STM32_DMAMUX1_TIM4_CH4 70 -#define STM32_DMAMUX1_TIM4_UP 71 -#define STM32_DMAMUX1_TIM5_CH1 72 -#define STM32_DMAMUX1_TIM5_CH2 73 -#define STM32_DMAMUX1_TIM5_CH3 74 -#define STM32_DMAMUX1_TIM5_CH4 75 -#define STM32_DMAMUX1_TIM5_UP 76 -#define STM32_DMAMUX1_TIM5_TRIG 77 -#define STM32_DMAMUX1_TIM15_CH1 78 -#define STM32_DMAMUX1_TIM15_UP 79 -#define STM32_DMAMUX1_TIM15_TRIG 80 -#define STM32_DMAMUX1_TIM15_COM 81 -#define STM32_DMAMUX1_TIM16_CH1 82 -#define STM32_DMAMUX1_TIM16_UP 83 -#define STM32_DMAMUX1_TIM17_CH1 84 -#define STM32_DMAMUX1_TIM17_UP 85 -#define STM32_DMAMUX1_TIM20_CH1 86 -#define STM32_DMAMUX1_TIM20_CH2 87 -#define STM32_DMAMUX1_TIM20_CH3 88 -#define STM32_DMAMUX1_TIM20_CH4 89 -#define STM32_DMAMUX1_TIM20_UP 90 -#define STM32_DMAMUX1_AES_IN 91 -#define STM32_DMAMUX1_AES_OUT 92 -#define STM32_DMAMUX1_TIM20_TRIG 93 -#define STM32_DMAMUX1_TIM20_COM 94 -#define STM32_DMAMUX1_HRTIM_MASTER 95 -#define STM32_DMAMUX1_HRTIM_TIMA 96 -#define STM32_DMAMUX1_HRTIM_TIMB 97 -#define STM32_DMAMUX1_HRTIM_TIMC 98 -#define STM32_DMAMUX1_HRTIM_TIMD 99 -#define STM32_DMAMUX1_HRTIM_TIME 100 -#define STM32_DMAMUX1_HRTIM_TIMF 101 -#define STM32_DMAMUX1_DAC3_CH1 102 -#define STM32_DMAMUX1_DAC3_CH2 103 -#define STM32_DMAMUX1_DAC4_CH1 104 -#define STM32_DMAMUX1_DAC4_CH2 105 -#define STM32_DMAMUX1_SPI4_RX 106 -#define STM32_DMAMUX1_SPI4_TX 107 -#define STM32_DMAMUX1_SAI1_A 108 -#define STM32_DMAMUX1_SAI1_B 109 -#define STM32_DMAMUX1_FMAC_READ 110 -#define STM32_DMAMUX1_FMAC_WRITE 111 -#define STM32_DMAMUX1_CORDIC_READ 112 -#define STM32_DMAMUX1_CORDIC_WRITE 113 -#define STM32_DMAMUX1_UCPD1_RX 114 -#define STM32_DMAMUX1_UCPD1_TX 115 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMAMUX_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/stm32_dmamux.h + * @brief STM32G4xx DMAMUX handler header. + * + * @addtogroup STM32G4xx_DMAMUX + * @{ + */ + +#ifndef STM32_DMAMUX_H +#define STM32_DMAMUX_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name DMAMUX1 request sources + * @{ + */ +#define STM32_DMAMUX1_REQ_GEN0 1 +#define STM32_DMAMUX1_REQ_GEN1 2 +#define STM32_DMAMUX1_REQ_GEN2 3 +#define STM32_DMAMUX1_REQ_GEN3 4 +#define STM32_DMAMUX1_ADC1 5 +#define STM32_DMAMUX1_DAC1_CH1 6 +#define STM32_DMAMUX1_DAC1_CH2 7 +#define STM32_DMAMUX1_TIM6_UP 8 +#define STM32_DMAMUX1_TIM7_UP 9 +#define STM32_DMAMUX1_SPI1_RX 10 +#define STM32_DMAMUX1_SPI1_TX 11 +#define STM32_DMAMUX1_SPI2_RX 12 +#define STM32_DMAMUX1_SPI2_TX 13 +#define STM32_DMAMUX1_SPI3_RX 14 +#define STM32_DMAMUX1_SPI3_TX 15 +#define STM32_DMAMUX1_I2C1_RX 16 +#define STM32_DMAMUX1_I2C1_TX 17 +#define STM32_DMAMUX1_I2C2_RX 18 +#define STM32_DMAMUX1_I2C2_TX 19 +#define STM32_DMAMUX1_I2C3_RX 20 +#define STM32_DMAMUX1_I2C3_TX 21 +#define STM32_DMAMUX1_I2C4_RX 22 +#define STM32_DMAMUX1_I2C4_TX 23 +#define STM32_DMAMUX1_USART1_RX 24 +#define STM32_DMAMUX1_USART1_TX 25 +#define STM32_DMAMUX1_USART2_RX 26 +#define STM32_DMAMUX1_USART2_TX 27 +#define STM32_DMAMUX1_USART3_RX 28 +#define STM32_DMAMUX1_USART3_TX 29 +#define STM32_DMAMUX1_UART4_RX 30 +#define STM32_DMAMUX1_UART4_TX 31 +#define STM32_DMAMUX1_UART5_RX 32 +#define STM32_DMAMUX1_UART5_TX 33 +#define STM32_DMAMUX1_LPUART1_RX 34 +#define STM32_DMAMUX1_LPUART1_TX 35 +#define STM32_DMAMUX1_ADC2 36 +#define STM32_DMAMUX1_ADC3 37 +#define STM32_DMAMUX1_ADC4 38 +#define STM32_DMAMUX1_ADC5 39 +#define STM32_DMAMUX1_QUADSPI 40 +#define STM32_DMAMUX1_DAC2_CH1 41 +#define STM32_DMAMUX1_TIM1_CH1 42 +#define STM32_DMAMUX1_TIM1_CH2 43 +#define STM32_DMAMUX1_TIM1_CH3 44 +#define STM32_DMAMUX1_TIM1_CH4 45 +#define STM32_DMAMUX1_TIM1_UP 46 +#define STM32_DMAMUX1_TIM1_TRIG 47 +#define STM32_DMAMUX1_TIM1_COM 48 +#define STM32_DMAMUX1_TIM8_CH1 49 +#define STM32_DMAMUX1_TIM8_CH2 50 +#define STM32_DMAMUX1_TIM8_CH3 51 +#define STM32_DMAMUX1_TIM8_CH4 52 +#define STM32_DMAMUX1_TIM8_UP 53 +#define STM32_DMAMUX1_TIM8_TRIG 54 +#define STM32_DMAMUX1_TIM8_COM 55 +#define STM32_DMAMUX1_TIM2_CH1 56 +#define STM32_DMAMUX1_TIM2_CH2 57 +#define STM32_DMAMUX1_TIM2_CH3 58 +#define STM32_DMAMUX1_TIM2_CH4 59 +#define STM32_DMAMUX1_TIM2_UP 60 +#define STM32_DMAMUX1_TIM3_CH1 61 +#define STM32_DMAMUX1_TIM3_CH2 62 +#define STM32_DMAMUX1_TIM3_CH3 63 +#define STM32_DMAMUX1_TIM3_CH4 64 +#define STM32_DMAMUX1_TIM3_UP 65 +#define STM32_DMAMUX1_TIM3_TRIG 66 +#define STM32_DMAMUX1_TIM4_CH1 67 +#define STM32_DMAMUX1_TIM4_CH2 68 +#define STM32_DMAMUX1_TIM4_CH3 69 +#define STM32_DMAMUX1_TIM4_CH4 70 +#define STM32_DMAMUX1_TIM4_UP 71 +#define STM32_DMAMUX1_TIM5_CH1 72 +#define STM32_DMAMUX1_TIM5_CH2 73 +#define STM32_DMAMUX1_TIM5_CH3 74 +#define STM32_DMAMUX1_TIM5_CH4 75 +#define STM32_DMAMUX1_TIM5_UP 76 +#define STM32_DMAMUX1_TIM5_TRIG 77 +#define STM32_DMAMUX1_TIM15_CH1 78 +#define STM32_DMAMUX1_TIM15_UP 79 +#define STM32_DMAMUX1_TIM15_TRIG 80 +#define STM32_DMAMUX1_TIM15_COM 81 +#define STM32_DMAMUX1_TIM16_CH1 82 +#define STM32_DMAMUX1_TIM16_UP 83 +#define STM32_DMAMUX1_TIM17_CH1 84 +#define STM32_DMAMUX1_TIM17_UP 85 +#define STM32_DMAMUX1_TIM20_CH1 86 +#define STM32_DMAMUX1_TIM20_CH2 87 +#define STM32_DMAMUX1_TIM20_CH3 88 +#define STM32_DMAMUX1_TIM20_CH4 89 +#define STM32_DMAMUX1_TIM20_UP 90 +#define STM32_DMAMUX1_AES_IN 91 +#define STM32_DMAMUX1_AES_OUT 92 +#define STM32_DMAMUX1_TIM20_TRIG 93 +#define STM32_DMAMUX1_TIM20_COM 94 +#define STM32_DMAMUX1_HRTIM_MASTER 95 +#define STM32_DMAMUX1_HRTIM_TIMA 96 +#define STM32_DMAMUX1_HRTIM_TIMB 97 +#define STM32_DMAMUX1_HRTIM_TIMC 98 +#define STM32_DMAMUX1_HRTIM_TIMD 99 +#define STM32_DMAMUX1_HRTIM_TIME 100 +#define STM32_DMAMUX1_HRTIM_TIMF 101 +#define STM32_DMAMUX1_DAC3_CH1 102 +#define STM32_DMAMUX1_DAC3_CH2 103 +#define STM32_DMAMUX1_DAC4_CH1 104 +#define STM32_DMAMUX1_DAC4_CH2 105 +#define STM32_DMAMUX1_SPI4_RX 106 +#define STM32_DMAMUX1_SPI4_TX 107 +#define STM32_DMAMUX1_SAI1_A 108 +#define STM32_DMAMUX1_SAI1_B 109 +#define STM32_DMAMUX1_FMAC_READ 110 +#define STM32_DMAMUX1_FMAC_WRITE 111 +#define STM32_DMAMUX1_CORDIC_READ 112 +#define STM32_DMAMUX1_CORDIC_WRITE 113 +#define STM32_DMAMUX1_UCPD1_RX 114 +#define STM32_DMAMUX1_UCPD1_TX 115 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMAMUX_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/stm32_isr.c b/os/hal/ports/STM32/STM32G4xx/stm32_isr.c index 44138bdbf7..53c0de59e8 100644 --- a/os/hal/ports/STM32/STM32G4xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32G4xx/stm32_isr.c @@ -1,183 +1,183 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/stm32_isr.c - * @brief STM32G4xx ISR handler code. - * - * @addtogroup STM32G4xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_exti0.inc" -#include "stm32_exti1.inc" -#include "stm32_exti2.inc" -#include "stm32_exti3.inc" -#include "stm32_exti4.inc" -#include "stm32_exti5_9.inc" -#include "stm32_exti10_15.inc" -#include "stm32_exti16-40_41.inc" -#include "stm32_exti17.inc" -#include "stm32_exti18.inc" -#include "stm32_exti19.inc" -#include "stm32_exti20.inc" -#include "stm32_exti21_22-29.inc" -#include "stm32_exti30_32.inc" -#include "stm32_exti33.inc" - -#include "stm32_fdcan1.inc" -#include "stm32_fdcan2.inc" -#include "stm32_fdcan3.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart3.inc" -#include "stm32_uart4.inc" -#include "stm32_uart5.inc" -#include "stm32_lpuart1.inc" - -#include "stm32_tim1_15_16_17.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim4.inc" -#include "stm32_tim5.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim8.inc" -#include "stm32_tim20.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_irq_init(); - exti1_irq_init(); - exti2_irq_init(); - exti3_irq_init(); - exti4_irq_init(); - exti5_9_irq_init(); - exti10_15_irq_init(); - exti16_exti40_exti41_irq_init(); - exti17_irq_init(); - exti18_irq_init(); - exti19_irq_init(); - exti21_exti22_exti29_irq_init(); - exti30_32_irq_init(); - exti33_irq_init(); - - fdcan1_irq_init(); - fdcan2_irq_init(); - fdcan3_irq_init(); - - tim1_tim15_tim16_tim17_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim4_irq_init(); - tim5_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim8_irq_init(); - tim20_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_irq_init(); - uart4_irq_init(); - uart5_irq_init(); - lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_irq_deinit(); - exti1_irq_deinit(); - exti2_irq_deinit(); - exti3_irq_deinit(); - exti4_irq_deinit(); - exti5_9_irq_deinit(); - exti10_15_irq_deinit(); - exti16_exti40_exti41_irq_deinit(); - exti17_irq_deinit(); - exti18_irq_deinit(); - exti19_irq_deinit(); - exti21_exti22_exti29_irq_deinit(); - exti30_32_irq_deinit(); - exti33_irq_deinit(); - - fdcan1_irq_deinit(); - fdcan2_irq_deinit(); - fdcan3_irq_deinit(); - - tim1_tim15_tim16_tim17_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim4_irq_deinit(); - tim5_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim8_irq_deinit(); - tim20_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_irq_deinit(); - uart4_irq_deinit(); - uart5_irq_deinit(); - lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/stm32_isr.c + * @brief STM32G4xx ISR handler code. + * + * @addtogroup STM32G4xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_exti0.inc" +#include "stm32_exti1.inc" +#include "stm32_exti2.inc" +#include "stm32_exti3.inc" +#include "stm32_exti4.inc" +#include "stm32_exti5_9.inc" +#include "stm32_exti10_15.inc" +#include "stm32_exti16-40_41.inc" +#include "stm32_exti17.inc" +#include "stm32_exti18.inc" +#include "stm32_exti19.inc" +#include "stm32_exti20.inc" +#include "stm32_exti21_22-29.inc" +#include "stm32_exti30_32.inc" +#include "stm32_exti33.inc" + +#include "stm32_fdcan1.inc" +#include "stm32_fdcan2.inc" +#include "stm32_fdcan3.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart3.inc" +#include "stm32_uart4.inc" +#include "stm32_uart5.inc" +#include "stm32_lpuart1.inc" + +#include "stm32_tim1_15_16_17.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim4.inc" +#include "stm32_tim5.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim8.inc" +#include "stm32_tim20.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_irq_init(); + exti1_irq_init(); + exti2_irq_init(); + exti3_irq_init(); + exti4_irq_init(); + exti5_9_irq_init(); + exti10_15_irq_init(); + exti16_exti40_exti41_irq_init(); + exti17_irq_init(); + exti18_irq_init(); + exti19_irq_init(); + exti21_exti22_exti29_irq_init(); + exti30_32_irq_init(); + exti33_irq_init(); + + fdcan1_irq_init(); + fdcan2_irq_init(); + fdcan3_irq_init(); + + tim1_tim15_tim16_tim17_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim4_irq_init(); + tim5_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim8_irq_init(); + tim20_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_irq_init(); + uart4_irq_init(); + uart5_irq_init(); + lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_irq_deinit(); + exti1_irq_deinit(); + exti2_irq_deinit(); + exti3_irq_deinit(); + exti4_irq_deinit(); + exti5_9_irq_deinit(); + exti10_15_irq_deinit(); + exti16_exti40_exti41_irq_deinit(); + exti17_irq_deinit(); + exti18_irq_deinit(); + exti19_irq_deinit(); + exti21_exti22_exti29_irq_deinit(); + exti30_32_irq_deinit(); + exti33_irq_deinit(); + + fdcan1_irq_deinit(); + fdcan2_irq_deinit(); + fdcan3_irq_deinit(); + + tim1_tim15_tim16_tim17_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim4_irq_deinit(); + tim5_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim8_irq_deinit(); + tim20_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_irq_deinit(); + uart4_irq_deinit(); + uart5_irq_deinit(); + lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/stm32_isr.h b/os/hal/ports/STM32/STM32G4xx/stm32_isr.h index 9445758ead..d1dfdd066d 100644 --- a/os/hal/ports/STM32/STM32G4xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32G4xx/stm32_isr.h @@ -1,298 +1,298 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/stm32_isr.h - * @brief STM32G4xx ISR handler header. - * - * @addtogroup STM32G4xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM8_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR -#define STM32_TIM20_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC unit. - */ -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC3_HANDLER VectorFC -#define STM32_ADC4_HANDLER Vector134 -#define STM32_ADC5_HANDLER Vector138 - -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC3_NUMBER 47 -#define STM32_ADC4_NUMBER 61 -#define STM32_ADC5_NUMBER 62 - -/* - * DMA unit. - */ -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#if !defined(STM32G431xx) && !defined(STM32G441xx) -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH8_HANDLER Vector1C0 -#endif -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH6_HANDLER Vector1C4 -#if !defined(STM32G431xx) && !defined(STM32G441xx) -#define STM32_DMA2_CH7_HANDLER Vector1C8 -#define STM32_DMA2_CH8_HANDLER Vector1CC -#endif - -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#if !defined(STM32G431xx) && !defined(STM32G441xx) -#define STM32_DMA1_CH7_NUMBER 17 -#define STM32_DMA1_CH8_NUMBER 96 -#endif -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 -#define STM32_DMA2_CH6_NUMBER 97 -#if !defined(STM32G431xx) && !defined(STM32G441xx) -#define STM32_DMA2_CH7_NUMBER 98 -#define STM32_DMA2_CH8_NUMBER 99 -#endif - -/* - * EXTI unit. - */ -#define STM32_EXTI0_HANDLER Vector58 -#define STM32_EXTI1_HANDLER Vector5C -#define STM32_EXTI2_HANDLER Vector60 -#define STM32_EXTI3_HANDLER Vector64 -#define STM32_EXTI4_HANDLER Vector68 -#define STM32_EXTI5_9_HANDLER Vector9C -#define STM32_EXTI10_15_HANDLER VectorE0 -#define STM32_EXTI164041_HANDLER Vector44 /* PVD PVM */ -#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */ -#define STM32_EXTI18_HANDLER VectorE8 /* USB WAKEUP */ -#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */ -#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */ -#define STM32_EXTI212229_HANDLER Vector140 /* COMP1..3 */ -#define STM32_EXTI30_32_HANDLER Vector144 /* COMP4..6 */ -#define STM32_EXTI33_HANDLER Vector148 /* COMP7 */ - -#define STM32_EXTI0_NUMBER 6 -#define STM32_EXTI1_NUMBER 7 -#define STM32_EXTI2_NUMBER 8 -#define STM32_EXTI3_NUMBER 9 -#define STM32_EXTI4_NUMBER 10 -#define STM32_EXTI5_9_NUMBER 23 -#define STM32_EXTI10_15_NUMBER 40 -#define STM32_EXTI164041_NUMBER 1 -#define STM32_EXTI17_NUMBER 41 -#define STM32_EXTI18_NUMBER 42 -#define STM32_EXTI19_NUMBER 2 -#define STM32_EXTI20_NUMBER 3 -#define STM32_EXTI212229_NUMBER 64 -#define STM32_EXTI30_32_NUMBER 65 -#define STM32_EXTI33_NUMBER 66 - -/* - * FDCAN units. - */ -#define STM32_FDCAN1_IT0_HANDLER Vector94 -#define STM32_FDCAN1_IT1_HANDLER Vector98 -#define STM32_FDCAN2_IT0_HANDLER Vector198 -#define STM32_FDCAN2_IT1_HANDLER Vector19C -#define STM32_FDCAN3_IT0_HANDLER Vector1A0 -#define STM32_FDCAN3_IT1_HANDLER Vector1A4 - -#define STM32_FDCAN1_IT0_NUMBER 21 -#define STM32_FDCAN1_IT1_NUMBER 22 -#define STM32_FDCAN2_IT0_NUMBER 86 -#define STM32_FDCAN2_IT1_NUMBER 87 -#define STM32_FDCAN3_IT0_NUMBER 88 -#define STM32_FDCAN3_IT1_NUMBER 89 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C3_EVENT_HANDLER Vector1B0 -#define STM32_I2C3_ERROR_HANDLER Vector1B4 -#define STM32_I2C4_EVENT_HANDLER Vector188 -#define STM32_I2C4_ERROR_HANDLER Vector18C - -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 -#define STM32_I2C3_EVENT_NUMBER 92 -#define STM32_I2C3_ERROR_NUMBER 93 -#define STM32_I2C4_EVENT_NUMBER 82 -#define STM32_I2C4_ERROR_NUMBER 83 - -/* - * QUADSPI unit. - */ -#define STM32_QUADSPI1_HANDLER Vector1BC -#define STM32_QUADSPI1_NUMBER 95 - -/* - * TIM units. - */ -#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0 -#define STM32_TIM1_UP_TIM16_HANDLER VectorA4 -#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_BRK_HANDLER VectorEC -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_TRGCO_HANDLER VectorF4 -#define STM32_TIM8_CC_HANDLER VectorF8 -#define STM32_TIM20_BRK_HANDLER Vector174 -#define STM32_TIM20_UP_HANDLER Vector178 -#define STM32_TIM20_TRGCO_HANDLER Vector17C -#define STM32_TIM20_CC_HANDLER Vector180 - -#define STM32_TIM1_BRK_TIM15_NUMBER 24 -#define STM32_TIM1_UP_TIM16_NUMBER 25 -#define STM32_TIM1_TRGCO_TIM17_NUMBER 26 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_BRK_NUMBER 43 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_TRGCO_NUMBER 45 -#define STM32_TIM8_CC_NUMBER 46 -#define STM32_TIM20_BRK_NUMBER 77 -#define STM32_TIM20_UP_NUMBER 78 -#define STM32_TIM20_TRGCO_NUMBER 79 -#define STM32_TIM20_CC_NUMBER 80 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_LPUART1_HANDLER Vector1AC - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_LPUART1_NUMBER 91 - -/* - * USB units. - */ -#define STM32_USB1_HP_HANDLER Vector8C -#define STM32_USB1_LP_HANDLER Vector90 -#define STM32_USB1_HP_NUMBER 19 -#define STM32_USB1_LP_NUMBER 20 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/stm32_isr.h + * @brief STM32G4xx ISR handler header. + * + * @addtogroup STM32G4xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM8_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR +#define STM32_TIM20_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC unit. + */ +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC3_HANDLER VectorFC +#define STM32_ADC4_HANDLER Vector134 +#define STM32_ADC5_HANDLER Vector138 + +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC3_NUMBER 47 +#define STM32_ADC4_NUMBER 61 +#define STM32_ADC5_NUMBER 62 + +/* + * DMA unit. + */ +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#if !defined(STM32G431xx) && !defined(STM32G441xx) +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH8_HANDLER Vector1C0 +#endif +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH6_HANDLER Vector1C4 +#if !defined(STM32G431xx) && !defined(STM32G441xx) +#define STM32_DMA2_CH7_HANDLER Vector1C8 +#define STM32_DMA2_CH8_HANDLER Vector1CC +#endif + +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#if !defined(STM32G431xx) && !defined(STM32G441xx) +#define STM32_DMA1_CH7_NUMBER 17 +#define STM32_DMA1_CH8_NUMBER 96 +#endif +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 +#define STM32_DMA2_CH6_NUMBER 97 +#if !defined(STM32G431xx) && !defined(STM32G441xx) +#define STM32_DMA2_CH7_NUMBER 98 +#define STM32_DMA2_CH8_NUMBER 99 +#endif + +/* + * EXTI unit. + */ +#define STM32_EXTI0_HANDLER Vector58 +#define STM32_EXTI1_HANDLER Vector5C +#define STM32_EXTI2_HANDLER Vector60 +#define STM32_EXTI3_HANDLER Vector64 +#define STM32_EXTI4_HANDLER Vector68 +#define STM32_EXTI5_9_HANDLER Vector9C +#define STM32_EXTI10_15_HANDLER VectorE0 +#define STM32_EXTI164041_HANDLER Vector44 /* PVD PVM */ +#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */ +#define STM32_EXTI18_HANDLER VectorE8 /* USB WAKEUP */ +#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */ +#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */ +#define STM32_EXTI212229_HANDLER Vector140 /* COMP1..3 */ +#define STM32_EXTI30_32_HANDLER Vector144 /* COMP4..6 */ +#define STM32_EXTI33_HANDLER Vector148 /* COMP7 */ + +#define STM32_EXTI0_NUMBER 6 +#define STM32_EXTI1_NUMBER 7 +#define STM32_EXTI2_NUMBER 8 +#define STM32_EXTI3_NUMBER 9 +#define STM32_EXTI4_NUMBER 10 +#define STM32_EXTI5_9_NUMBER 23 +#define STM32_EXTI10_15_NUMBER 40 +#define STM32_EXTI164041_NUMBER 1 +#define STM32_EXTI17_NUMBER 41 +#define STM32_EXTI18_NUMBER 42 +#define STM32_EXTI19_NUMBER 2 +#define STM32_EXTI20_NUMBER 3 +#define STM32_EXTI212229_NUMBER 64 +#define STM32_EXTI30_32_NUMBER 65 +#define STM32_EXTI33_NUMBER 66 + +/* + * FDCAN units. + */ +#define STM32_FDCAN1_IT0_HANDLER Vector94 +#define STM32_FDCAN1_IT1_HANDLER Vector98 +#define STM32_FDCAN2_IT0_HANDLER Vector198 +#define STM32_FDCAN2_IT1_HANDLER Vector19C +#define STM32_FDCAN3_IT0_HANDLER Vector1A0 +#define STM32_FDCAN3_IT1_HANDLER Vector1A4 + +#define STM32_FDCAN1_IT0_NUMBER 21 +#define STM32_FDCAN1_IT1_NUMBER 22 +#define STM32_FDCAN2_IT0_NUMBER 86 +#define STM32_FDCAN2_IT1_NUMBER 87 +#define STM32_FDCAN3_IT0_NUMBER 88 +#define STM32_FDCAN3_IT1_NUMBER 89 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C3_EVENT_HANDLER Vector1B0 +#define STM32_I2C3_ERROR_HANDLER Vector1B4 +#define STM32_I2C4_EVENT_HANDLER Vector188 +#define STM32_I2C4_ERROR_HANDLER Vector18C + +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 +#define STM32_I2C3_EVENT_NUMBER 92 +#define STM32_I2C3_ERROR_NUMBER 93 +#define STM32_I2C4_EVENT_NUMBER 82 +#define STM32_I2C4_ERROR_NUMBER 83 + +/* + * QUADSPI unit. + */ +#define STM32_QUADSPI1_HANDLER Vector1BC +#define STM32_QUADSPI1_NUMBER 95 + +/* + * TIM units. + */ +#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0 +#define STM32_TIM1_UP_TIM16_HANDLER VectorA4 +#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_BRK_HANDLER VectorEC +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_TRGCO_HANDLER VectorF4 +#define STM32_TIM8_CC_HANDLER VectorF8 +#define STM32_TIM20_BRK_HANDLER Vector174 +#define STM32_TIM20_UP_HANDLER Vector178 +#define STM32_TIM20_TRGCO_HANDLER Vector17C +#define STM32_TIM20_CC_HANDLER Vector180 + +#define STM32_TIM1_BRK_TIM15_NUMBER 24 +#define STM32_TIM1_UP_TIM16_NUMBER 25 +#define STM32_TIM1_TRGCO_TIM17_NUMBER 26 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_BRK_NUMBER 43 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_TRGCO_NUMBER 45 +#define STM32_TIM8_CC_NUMBER 46 +#define STM32_TIM20_BRK_NUMBER 77 +#define STM32_TIM20_UP_NUMBER 78 +#define STM32_TIM20_TRGCO_NUMBER 79 +#define STM32_TIM20_CC_NUMBER 80 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_LPUART1_HANDLER Vector1AC + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_LPUART1_NUMBER 91 + +/* + * USB units. + */ +#define STM32_USB1_HP_HANDLER Vector8C +#define STM32_USB1_LP_HANDLER Vector90 +#define STM32_USB1_HP_NUMBER 19 +#define STM32_USB1_LP_NUMBER 20 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h b/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h index 9877f630d4..ba79dd899b 100644 --- a/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h @@ -1,1366 +1,1366 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32g4xx.h. - * - * @addtogroup STM32G4xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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 (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R1(mask, lp) { \ - RCC->APB1ENR1 |= (mask); \ - if (lp) \ - RCC->APB1SMENR1 |= (mask); \ - else \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccDisableAPB1R1(mask) { \ - RCC->APB1ENR1 &= ~(mask); \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccResetAPB1R1(mask) { \ - RCC->APB1RSTR1 |= (mask); \ - RCC->APB1RSTR1 &= ~(mask); \ - (void)RCC->APB1RSTR1; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R2(mask, lp) { \ - RCC->APB1ENR2 |= (mask); \ - if (lp) \ - RCC->APB1SMENR2 |= (mask); \ - else \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccDisableAPB1R2(mask) { \ - RCC->APB1ENR2 &= ~(mask); \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccResetAPB1R2(mask) { \ - RCC->APB1RSTR2 |= (mask); \ - RCC->APB1RSTR2 &= ~(mask); \ - (void)RCC->APB1RSTR2; \ -} - -/** - * @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->APB2SMENR |= (mask); \ - else \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @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->AHB1SMENR |= (mask); \ - else \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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->AHB2SMENR |= (mask); \ - else \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @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->AHB3SMENR |= (mask); \ - else \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC12(lp) rccEnableAHB2(RCC_AHB2ENR_ADC12EN, lp) - -/** - * @brief Disables the ADC1/ADC2 peripheral clock. - * - * @api - */ -#define rccDisableADC12() rccDisableAHB2(RCC_AHB2ENR_ADC12EN) - -/** - * @brief Resets the ADC1/ADC2 peripheral. - * - * @api - */ -#define rccResetADC12() rccResetAHB2(RCC_AHB2RSTR_ADC12RST) - -/** - * @brief Enables the ADC3/ADC4/ADC5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC345(lp) rccEnableAHB2(RCC_AHB2ENR_ADC345EN, lp) - -/** - * @brief Disables the ADC3/ADC4/ADC5 peripheral clock. - * - * @api - */ -#define rccDisableADC345() rccDisableAHB2(RCC_AHB2ENR_ADC345EN) - -/** - * @brief Resets the ADC3/ADC4/ADC5 peripheral. - * - * @api - */ -#define rccResetADC345() rccResetAHB2(RCC_AHB2RSTR_ADC345RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAHB2(RCC_AHB2ENR_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAHB2(RCC_AHB2ENR_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAHB2(RCC_AHB2RSTR_DAC1RST) - -/** - * @brief Enables the DAC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC2(lp) rccEnableAHB2(RCC_AHB2ENR_DAC2EN, lp) - -/** - * @brief Disables the DAC2 peripheral clock. - * - * @api - */ -#define rccDisableDAC2() rccDisableAHB2(RCC_AHB2ENR_DAC2EN) - -/** - * @brief Resets the DAC2 peripheral. - * - * @api - */ -#define rccResetDAC2() rccResetAHB2(RCC_AHB2RSTR_DAC2RST) - -/** - * @brief Enables the DAC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC3(lp) rccEnableAHB2(RCC_AHB2ENR_DAC3EN, lp) - -/** - * @brief Disables the DAC3 peripheral clock. - * - * @api - */ -#define rccDisableDAC3() rccDisableAHB2(RCC_AHB2ENR_DAC3EN) - -/** - * @brief Resets the DAC3 peripheral. - * - * @api - */ -#define rccResetDAC3() rccResetAHB2(RCC_AHB2RSTR_DAC3RST) - -/** - * @brief Enables the DAC4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC4(lp) rccEnableAHB2(RCC_AHB2ENR_DAC4EN, lp) - -/** - * @brief Disables the DAC4 peripheral clock. - * - * @api - */ -#define rccDisableDAC4() rccDisableAHB2(RCC_AHB2ENR_DAC4EN) - -/** - * @brief Resets the DAC4 peripheral. - * - * @api - */ -#define rccResetDAC4() rccResetAHB2(RCC_AHB2RSTR_DAC4RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name DMAMUX peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMAMUX peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp) - -/** - * @brief Disables the DMAMUX peripheral clock. - * - * @api - */ -#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN) - -/** - * @brief Resets the DMAMUX peripheral. - * - * @api - */ -#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST) -/** @} */ - -/** - * @name FDCAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FDCAN peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFDCAN(lp) rccEnableAPB1R1(RCC_APB1ENR1_FDCANEN, lp) - -/** - * @brief Disables the FDCAN peripheral clock. - * - * @api - */ -#define rccDisableFDCAN() rccDisableAPB1R1(RCC_APB1ENR1_FDCANEN) - -/** - * @brief Resets the FDCAN peripheral. - * - * @api - */ -#define rccResetFDCAN() rccResetAPB1R1(RCC_APB1RSTR1_FDCANRST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) -/** @} */ - -/** - * @name FDCAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FDCAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFDCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_FDCANEN, lp) - -/** - * @brief Disables the FDCAN1 peripheral clock. - * - * @api - */ -#define rccDisableFDCAN1() rccDisableAPB1R1(RCC_APB1ENR1_FDCANEN) - -/** - * @brief Resets the FDCAN1 peripheral. - * - * @api - */ -#define rccResetFDCAN1() rccResetAPB1R1(RCC_APB1RSTR1_FDCANRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) - -/** - * @brief Enables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) - -/** - * @brief Disables the I2C3 peripheral clock. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @api - */ -#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) -/** @} */ - -/** - * @name QUADSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the QUADSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) - -/** - * @brief Disables the QUADSPI1 peripheral clock. - * - * @api - */ -#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) - -/** - * @brief Resets the QUADSPI1 peripheral. - * - * @api - */ -#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) - -/** - * @brief Enables the SPI4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) - -/** - * @brief Disables the SPI4 peripheral clock. - * - * @api - */ -#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) - -/** - * @brief Resets the SPI4 peripheral. - * - * @api - */ -#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) - -/** - * @brief Enables the TIM20 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM20(lp) rccEnableAPB2(RCC_APB2ENR_TIM20EN, lp) - -/** - * @brief Disables the TIM20 peripheral clock. - * - * @api - */ -#define rccDisableTIM20() rccDisableAPB2(RCC_APB2ENR_TIM20EN) - -/** - * @brief Resets the TIM20 peripheral. - * - * @api - */ -#define rccResetTIM20() rccResetAPB2(RCC_APB2RSTR_TIM20RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBRST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32g4xx.h. + * + * @addtogroup STM32G4xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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 (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R1(mask, lp) { \ + RCC->APB1ENR1 |= (mask); \ + if (lp) \ + RCC->APB1SMENR1 |= (mask); \ + else \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccDisableAPB1R1(mask) { \ + RCC->APB1ENR1 &= ~(mask); \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccResetAPB1R1(mask) { \ + RCC->APB1RSTR1 |= (mask); \ + RCC->APB1RSTR1 &= ~(mask); \ + (void)RCC->APB1RSTR1; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R2(mask, lp) { \ + RCC->APB1ENR2 |= (mask); \ + if (lp) \ + RCC->APB1SMENR2 |= (mask); \ + else \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccDisableAPB1R2(mask) { \ + RCC->APB1ENR2 &= ~(mask); \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccResetAPB1R2(mask) { \ + RCC->APB1RSTR2 |= (mask); \ + RCC->APB1RSTR2 &= ~(mask); \ + (void)RCC->APB1RSTR2; \ +} + +/** + * @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->APB2SMENR |= (mask); \ + else \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @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->AHB1SMENR |= (mask); \ + else \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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->AHB2SMENR |= (mask); \ + else \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @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->AHB3SMENR |= (mask); \ + else \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC12(lp) rccEnableAHB2(RCC_AHB2ENR_ADC12EN, lp) + +/** + * @brief Disables the ADC1/ADC2 peripheral clock. + * + * @api + */ +#define rccDisableADC12() rccDisableAHB2(RCC_AHB2ENR_ADC12EN) + +/** + * @brief Resets the ADC1/ADC2 peripheral. + * + * @api + */ +#define rccResetADC12() rccResetAHB2(RCC_AHB2RSTR_ADC12RST) + +/** + * @brief Enables the ADC3/ADC4/ADC5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC345(lp) rccEnableAHB2(RCC_AHB2ENR_ADC345EN, lp) + +/** + * @brief Disables the ADC3/ADC4/ADC5 peripheral clock. + * + * @api + */ +#define rccDisableADC345() rccDisableAHB2(RCC_AHB2ENR_ADC345EN) + +/** + * @brief Resets the ADC3/ADC4/ADC5 peripheral. + * + * @api + */ +#define rccResetADC345() rccResetAHB2(RCC_AHB2RSTR_ADC345RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAHB2(RCC_AHB2ENR_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAHB2(RCC_AHB2ENR_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAHB2(RCC_AHB2RSTR_DAC1RST) + +/** + * @brief Enables the DAC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC2(lp) rccEnableAHB2(RCC_AHB2ENR_DAC2EN, lp) + +/** + * @brief Disables the DAC2 peripheral clock. + * + * @api + */ +#define rccDisableDAC2() rccDisableAHB2(RCC_AHB2ENR_DAC2EN) + +/** + * @brief Resets the DAC2 peripheral. + * + * @api + */ +#define rccResetDAC2() rccResetAHB2(RCC_AHB2RSTR_DAC2RST) + +/** + * @brief Enables the DAC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC3(lp) rccEnableAHB2(RCC_AHB2ENR_DAC3EN, lp) + +/** + * @brief Disables the DAC3 peripheral clock. + * + * @api + */ +#define rccDisableDAC3() rccDisableAHB2(RCC_AHB2ENR_DAC3EN) + +/** + * @brief Resets the DAC3 peripheral. + * + * @api + */ +#define rccResetDAC3() rccResetAHB2(RCC_AHB2RSTR_DAC3RST) + +/** + * @brief Enables the DAC4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC4(lp) rccEnableAHB2(RCC_AHB2ENR_DAC4EN, lp) + +/** + * @brief Disables the DAC4 peripheral clock. + * + * @api + */ +#define rccDisableDAC4() rccDisableAHB2(RCC_AHB2ENR_DAC4EN) + +/** + * @brief Resets the DAC4 peripheral. + * + * @api + */ +#define rccResetDAC4() rccResetAHB2(RCC_AHB2RSTR_DAC4RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name DMAMUX peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMAMUX peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp) + +/** + * @brief Disables the DMAMUX peripheral clock. + * + * @api + */ +#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN) + +/** + * @brief Resets the DMAMUX peripheral. + * + * @api + */ +#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST) +/** @} */ + +/** + * @name FDCAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FDCAN peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFDCAN(lp) rccEnableAPB1R1(RCC_APB1ENR1_FDCANEN, lp) + +/** + * @brief Disables the FDCAN peripheral clock. + * + * @api + */ +#define rccDisableFDCAN() rccDisableAPB1R1(RCC_APB1ENR1_FDCANEN) + +/** + * @brief Resets the FDCAN peripheral. + * + * @api + */ +#define rccResetFDCAN() rccResetAPB1R1(RCC_APB1RSTR1_FDCANRST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) +/** @} */ + +/** + * @name FDCAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FDCAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFDCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_FDCANEN, lp) + +/** + * @brief Disables the FDCAN1 peripheral clock. + * + * @api + */ +#define rccDisableFDCAN1() rccDisableAPB1R1(RCC_APB1ENR1_FDCANEN) + +/** + * @brief Resets the FDCAN1 peripheral. + * + * @api + */ +#define rccResetFDCAN1() rccResetAPB1R1(RCC_APB1RSTR1_FDCANRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) + +/** + * @brief Enables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) + +/** + * @brief Disables the I2C3 peripheral clock. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @api + */ +#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) +/** @} */ + +/** + * @name QUADSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the QUADSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) + +/** + * @brief Disables the QUADSPI1 peripheral clock. + * + * @api + */ +#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) + +/** + * @brief Resets the QUADSPI1 peripheral. + * + * @api + */ +#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) + +/** + * @brief Enables the SPI4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) + +/** + * @brief Disables the SPI4 peripheral clock. + * + * @api + */ +#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) + +/** + * @brief Resets the SPI4 peripheral. + * + * @api + */ +#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) + +/** + * @brief Enables the TIM20 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM20(lp) rccEnableAPB2(RCC_APB2ENR_TIM20EN, lp) + +/** + * @brief Disables the TIM20 peripheral clock. + * + * @api + */ +#define rccDisableTIM20() rccDisableAPB2(RCC_APB2ENR_TIM20EN) + +/** + * @brief Resets the TIM20 peripheral. + * + * @api + */ +#define rccResetTIM20() rccResetAPB2(RCC_APB2RSTR_TIM20RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBRST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/stm32_registry.h b/os/hal/ports/STM32/STM32G4xx/stm32_registry.h index f86ef00141..b9dd413daf 100644 --- a/os/hal/ports/STM32/STM32G4xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32G4xx/stm32_registry.h @@ -1,524 +1,524 @@ -/* - ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32G4xx/stm32_registry.h - * @brief STM32G4xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32G4xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 128 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 18 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ -} while (false) - - /* Enabling RTC-related EXTI lines.*/ -#define STM32_RTC_ENABLE_ALL_EXTI() do { \ - extiEnableGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | \ - EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | \ - EXTI_MASK1(STM32_RTC_WKUP_EXTI), \ - EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); \ -} while (false) - -/* Clearing EXTI interrupts. */ -#define STM32_RTC_CLEAR_ALL_EXTI() do { \ - extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | \ - EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | \ - EXTI_MASK1(STM32_RTC_WKUP_EXTI)); \ -} while (false) - -/* Masks used to preserve state of RTC and TAMP register reserved bits. */ -#define STM32_RTC_CR_MASK 0xE7FFFF7F -#define STM32_RTC_PRER_MASK 0x007F7FFF -#define STM32_TAMP_CR1_MASK 0x003C0007 -#define STM32_TAMP_CR2_MASK 0x07070007 -#define STM32_TAMP_FLTCR_MASK 0x000000FF -#define STM32_TAMP_IER_MASK 0x003C0007 - -#if defined(STM32G441xx) || defined(STM32G483xx) || defined(STM32G484xx) || \ - defined(__DOXYGEN__) -#define STM32_HAS_HASH1 TRUE -#define STM32_HAS_CRYP1 TRUE -#else -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE -#endif - -/*===========================================================================*/ -/* STM32G473xx, STM32G4843xx, STM32G474xx, STM32G484xx. */ -/*===========================================================================*/ - -#if defined(STM32G473xx) || defined(STM32G483xx) || \ - defined(STM32G474xx) || defined(STM32G484xx) || \ - defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 TRUE -#define STM32_HAS_ADC4 TRUE -#define STM32_HAS_ADC5 TRUE - -/* CAN attributes.*/ -#define STM32_HAS_FDCAN1 TRUE -#define STM32_HAS_FDCAN2 TRUE -#define STM32_HAS_FDCAN3 TRUE -#define STM32_FDCAN_FLS_NBR 28U -#define STM32_FDCAN_FLE_NBR 8U -#define STM32_FDCAN_RF0_NBR 3U -#define STM32_FDCAN_RF1_NBR 3U -#define STM32_FDCAN_RB_NBR 0U -#define STM32_FDCAN_TEF_NBR 3U -#define STM32_FDCAN_TB_NBR 3U -#define STM32_FDCAN_TM_NBR 0U - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_HAS_DAC2_CH2 FALSE -#define STM32_HAS_DAC3_CH1 TRUE -#define STM32_HAS_DAC3_CH2 TRUE -#define STM32_HAS_DAC4_CH1 TRUE -#define STM32_HAS_DAC4_CH2 TRUE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 8 -#define STM32_DMA2_NUM_CHANNELS 8 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_HAS_CR FALSE -#define STM32_EXTI_SEPARATE_RF FALSE -#define STM32_EXTI_NUM_LINES 44 -#define STM32_EXTI_IMR1_MASK 0x1F840000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF3CU - - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOFEN | \ - RCC_AHB2ENR_GPIOGEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 TRUE -#define STM32_HAS_I2C4 TRUE - -/* OCTOSPI attributes.*/ -#define STM32_HAS_OCTOSPI1 FALSE -#define STM32_HAS_OCTOSPI2 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 FALSE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM20 TRUE -#define STM32_TIM20_IS_32BITS FALSE -#define STM32_TIM20_CHANNELS 6 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_UART5 TRUE -#define STM32_HAS_LPUART1 TRUE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* OTG/USB attributes.*/ -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI FALSE - -#endif /* defined(STM32G474xx) || defined(STM32G484xx) */ - -/*===========================================================================*/ -/* STM32G431xx, STM32G441xx, STM32G471xx. */ -/*===========================================================================*/ - -#if defined(STM32G431xx) || defined(STM32G441xx) || \ - defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE -#define STM32_HAS_ADC5 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_FDCAN1 TRUE -#define STM32_HAS_FDCAN2 FALSE -#define STM32_HAS_FDCAN3 FALSE -#define STM32_FDCAN_FLS_NBR 28U -#define STM32_FDCAN_FLE_NBR 8U -#define STM32_FDCAN_RF0_NBR 3U -#define STM32_FDCAN_RF1_NBR 3U -#define STM32_FDCAN_RB_NBR 0U -#define STM32_FDCAN_TEF_NBR 3U -#define STM32_FDCAN_TB_NBR 3U -#define STM32_FDCAN_TM_NBR 0U - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE -#define STM32_HAS_DAC3_CH1 TRUE -#define STM32_HAS_DAC3_CH2 TRUE -#define STM32_HAS_DAC4_CH1 FALSE -#define STM32_HAS_DAC4_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 6 -#define STM32_DMA2_NUM_CHANNELS 6 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_HAS_CR FALSE -#define STM32_EXTI_SEPARATE_RF FALSE -#define STM32_EXTI_NUM_LINES 44 -#define STM32_EXTI_IMR1_MASK 0x1F840000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF3CU - - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOFEN | \ - RCC_AHB2ENR_GPIOGEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 TRUE -#define STM32_HAS_I2C4 FALSE - -/* OCTOSPI attributes.*/ -#define STM32_HAS_OCTOSPI1 FALSE -#define STM32_HAS_OCTOSPI2 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 FALSE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_LPUART1 TRUE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* OTG/USB attributes.*/ -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI FALSE - -#endif /* defined(STM32G431xx) || defined(STM32G441xx) */ - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32G4xx/stm32_registry.h + * @brief STM32G4xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32G4xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 18 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ +} while (false) + + /* Enabling RTC-related EXTI lines.*/ +#define STM32_RTC_ENABLE_ALL_EXTI() do { \ + extiEnableGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | \ + EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | \ + EXTI_MASK1(STM32_RTC_WKUP_EXTI), \ + EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); \ +} while (false) + +/* Clearing EXTI interrupts. */ +#define STM32_RTC_CLEAR_ALL_EXTI() do { \ + extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | \ + EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | \ + EXTI_MASK1(STM32_RTC_WKUP_EXTI)); \ +} while (false) + +/* Masks used to preserve state of RTC and TAMP register reserved bits. */ +#define STM32_RTC_CR_MASK 0xE7FFFF7F +#define STM32_RTC_PRER_MASK 0x007F7FFF +#define STM32_TAMP_CR1_MASK 0x003C0007 +#define STM32_TAMP_CR2_MASK 0x07070007 +#define STM32_TAMP_FLTCR_MASK 0x000000FF +#define STM32_TAMP_IER_MASK 0x003C0007 + +#if defined(STM32G441xx) || defined(STM32G483xx) || defined(STM32G484xx) || \ + defined(__DOXYGEN__) +#define STM32_HAS_HASH1 TRUE +#define STM32_HAS_CRYP1 TRUE +#else +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE +#endif + +/*===========================================================================*/ +/* STM32G473xx, STM32G4843xx, STM32G474xx, STM32G484xx. */ +/*===========================================================================*/ + +#if defined(STM32G473xx) || defined(STM32G483xx) || \ + defined(STM32G474xx) || defined(STM32G484xx) || \ + defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 TRUE +#define STM32_HAS_ADC4 TRUE +#define STM32_HAS_ADC5 TRUE + +/* CAN attributes.*/ +#define STM32_HAS_FDCAN1 TRUE +#define STM32_HAS_FDCAN2 TRUE +#define STM32_HAS_FDCAN3 TRUE +#define STM32_FDCAN_FLS_NBR 28U +#define STM32_FDCAN_FLE_NBR 8U +#define STM32_FDCAN_RF0_NBR 3U +#define STM32_FDCAN_RF1_NBR 3U +#define STM32_FDCAN_RB_NBR 0U +#define STM32_FDCAN_TEF_NBR 3U +#define STM32_FDCAN_TB_NBR 3U +#define STM32_FDCAN_TM_NBR 0U + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_HAS_DAC2_CH2 FALSE +#define STM32_HAS_DAC3_CH1 TRUE +#define STM32_HAS_DAC3_CH2 TRUE +#define STM32_HAS_DAC4_CH1 TRUE +#define STM32_HAS_DAC4_CH2 TRUE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 8 +#define STM32_DMA2_NUM_CHANNELS 8 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_HAS_CR FALSE +#define STM32_EXTI_SEPARATE_RF FALSE +#define STM32_EXTI_NUM_LINES 44 +#define STM32_EXTI_IMR1_MASK 0x1F840000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF3CU + + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOFEN | \ + RCC_AHB2ENR_GPIOGEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 TRUE +#define STM32_HAS_I2C4 TRUE + +/* OCTOSPI attributes.*/ +#define STM32_HAS_OCTOSPI1 FALSE +#define STM32_HAS_OCTOSPI2 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 FALSE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM20 TRUE +#define STM32_TIM20_IS_32BITS FALSE +#define STM32_TIM20_CHANNELS 6 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_UART5 TRUE +#define STM32_HAS_LPUART1 TRUE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* OTG/USB attributes.*/ +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI FALSE + +#endif /* defined(STM32G474xx) || defined(STM32G484xx) */ + +/*===========================================================================*/ +/* STM32G431xx, STM32G441xx, STM32G471xx. */ +/*===========================================================================*/ + +#if defined(STM32G431xx) || defined(STM32G441xx) || \ + defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE +#define STM32_HAS_ADC5 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_FDCAN1 TRUE +#define STM32_HAS_FDCAN2 FALSE +#define STM32_HAS_FDCAN3 FALSE +#define STM32_FDCAN_FLS_NBR 28U +#define STM32_FDCAN_FLE_NBR 8U +#define STM32_FDCAN_RF0_NBR 3U +#define STM32_FDCAN_RF1_NBR 3U +#define STM32_FDCAN_RB_NBR 0U +#define STM32_FDCAN_TEF_NBR 3U +#define STM32_FDCAN_TB_NBR 3U +#define STM32_FDCAN_TM_NBR 0U + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE +#define STM32_HAS_DAC3_CH1 TRUE +#define STM32_HAS_DAC3_CH2 TRUE +#define STM32_HAS_DAC4_CH1 FALSE +#define STM32_HAS_DAC4_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 6 +#define STM32_DMA2_NUM_CHANNELS 6 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_HAS_CR FALSE +#define STM32_EXTI_SEPARATE_RF FALSE +#define STM32_EXTI_NUM_LINES 44 +#define STM32_EXTI_IMR1_MASK 0x1F840000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF3CU + + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOFEN | \ + RCC_AHB2ENR_GPIOGEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 TRUE +#define STM32_HAS_I2C4 FALSE + +/* OCTOSPI attributes.*/ +#define STM32_HAS_OCTOSPI1 FALSE +#define STM32_HAS_OCTOSPI2 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 FALSE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_LPUART1 TRUE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* OTG/USB attributes.*/ +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI FALSE + +#endif /* defined(STM32G431xx) || defined(STM32G441xx) */ + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/hal_lld.c b/os/hal/ports/STM32/STM32H7xx/hal_lld.c index 4f1de78e4f..106324aa45 100644 --- a/os/hal/ports/STM32/STM32H7xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32H7xx/hal_lld.c @@ -1,439 +1,440 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32H7xx/hal_lld.c - * @brief STM32H7xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f7xx.h. - */ -uint32_t SystemCoreClock = STM32_CORE_CK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static inline void init_bkp_domain(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR1 |= PWR_CR1_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ -} - -/** - * @brief Initializes the PWR unit. - */ -static inline void init_pwr(void) { -#if 0 - PWR_TypeDef *pwr = PWR; /* For inspection.*/ - (void)pwr; -#endif - - /* Lower C3 byte, it must be programmed at very first, then waiting for - power supply to stabilize.*/ - PWR->CR3 = STM32_PWR_CR3 & 0x000000FFU; - while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0) - ; /* CHTODO timeout handling.*/ - - PWR->CR1 = STM32_PWR_CR1 | 0xF0000000U; - PWR->CR2 = STM32_PWR_CR2; - PWR->CR3 = STM32_PWR_CR3; /* Other bits, lower byte is not changed. */ - PWR->CPUCR = STM32_PWR_CPUCR; - PWR->D3CR = STM32_VOS; -#if !defined(STM32_ENFORCE_H7_REV_XY) - SYSCFG->PWRCR = STM32_ODEN; -#endif - while ((PWR->D3CR & PWR_D3CR_VOSRDY) == 0) - ; /* CHTODO timeout handling.*/ -#if STM32_PWR_CR2 & PWR_CR2_BREN -// while ((PWR->CR2 & PWR_CR2_BRRDY) == 0) -// ; -// rccEnableBKPRAM(true); -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - -#if STM32_NO_INIT == FALSE - /* Reset of all peripherals. AHB3 is not reset entirely because FMC could - have been initialized in the board initialization file (board.c). - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB1(~0); - rccResetAHB2(~0); - rccResetAHB3(~(RCC_AHB3RSTR_FMCRST | - 0x80000000U)); /* Was RCC_AHB3RSTR_CPURST in Rev-V.*/ - rccResetAHB4(~(RCC_APB4RSTR_SYSCFGRST | STM32_GPIO_EN_MASK)); - rccResetAPB1L(~0); - rccResetAPB1H(~0); - rccResetAPB2(~0); - rccResetAPB3(~0); - rccResetAPB4(~0); -#endif /* STM32_NO_INIT == FALSE */ - - /* DMA subsystems initialization.*/ -#if defined(STM32_BDMA_REQUIRED) - bdmaInit(); -#endif -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif -#if defined(STM32_MDMA_REQUIRED) - mdmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* MPU initialization.*/ -#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) || (STM32_NOCACHE_SRAM3 == TRUE) - { - uint32_t base, size; - -#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == TRUE) - base = 0x30000000U; - size = MPU_RASR_SIZE_512K; -#elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == FALSE) - base = 0x30000000U; - size = MPU_RASR_SIZE_256K; -#elif (STM32_NOCACHE_SRAM1_SRAM2 == FALSE) && (STM32_NOCACHE_SRAM3 == TRUE) - base = 0x30040000U; - size = MPU_RASR_SIZE_16K; -#else -#error "invalid constants used in mcuconf.h" -#endif - - /* The SRAM2 bank can optionally made a non cache-able area for use by - DMA engines.*/ - mpuConfigureRegion(STM32_NOCACHE_MPU_REGION, - base, - MPU_RASR_ATTR_AP_RW_RW | - MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_ATTR_S | - size | - MPU_RASR_ENABLE); - mpuEnable(MPU_CTRL_PRIVDEFENA); - - /* Invalidating data cache to make sure that the MPU settings are taken - immediately.*/ - SCB_CleanInvalidateDCache(); - } -#endif -} - -/** - * @brief STM32H7xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { -#if STM32_NO_INIT == FALSE - uint32_t cfgr; - -#if 0 - RCC_TypeDef *rcc = RCC; /* For inspection.*/ - (void)rcc; -#endif - -#if defined(STM32_ENFORCE_H7_REV_XY) - /* Fix for errata 2.2.15: Reading from AXI SRAM might lead to data - read corruption. - AXI->TARG7_FN_MOD.*/ - *((volatile uint32_t *)(0x51000000 + 0x1108 + 0x7000)) = 0x00000001U; -#endif - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB4(RCC_APB4ENR_SYSCFGEN, true); - - /* PWR initialization.*/ - init_pwr(); - - /* Backup domain initialization.*/ - init_bkp_domain(); - - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - - /* HSI is selected as new source without touching the other fields in - CFGR. This is only required when using a debugger than can cause - restarts.*/ - RCC->CFGR = 0x00000000U; /* Reset SW to HSI. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Wait until HSI is selected. */ - - /* Registers cleared to reset values.*/ - RCC->CR = RCC_CR_HSION; /* CR Reset value. */ - RCC->HSICFGR = 0x40000000U; /* HSICFGR Reset value. */ -#if !defined(STM32_ENFORCE_H7_REV_XY) - RCC->CSICFGR = 0x20000000U; /* CSICFGR Reset value. */ -#endif - RCC->CSR = 0x00000000U; /* CSR reset value. */ - RCC->PLLCFGR = 0x01FF0000U; /* PLLCFGR reset value. */ - - /* Other clock-related settings, done before other things because - recommended in the RM.*/ - cfgr = STM32_MCO2SEL | RCC_CFGR_MCO2PRE_VALUE(STM32_MCO2PRE_VALUE) | - STM32_MCO1SEL | RCC_CFGR_MCO1PRE_VALUE(STM32_MCO1PRE_VALUE) | - RCC_CFGR_RTCPRE_VALUE(STM32_RTCPRE_VALUE) | - STM32_HRTIMSEL | STM32_STOPKERWUCK | STM32_STOPWUCK; -#if STM32_TIMPRE_ENABLE == TRUE - cfgr |= RCC_CFGR_TIMPRE; -#endif - RCC->CFGR = cfgr; - - /* HSE activation with optional bypass.*/ -#if STM32_HSE_ENABLED == TRUE -#if defined(STM32_HSE_BYPASS) - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - RCC->CR |= RCC_CR_HSEON; -#endif - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Waits until HSE is stable. */ -#endif /* STM32_HSE_ENABLED == TRUE */ - - /* HSI48 activation.*/ -#if STM32_HSI48_ENABLED == TRUE - RCC->CR |= RCC_CR_HSI48ON; - while ((RCC->CR & RCC_CR_HSI48RDY) == 0) - ; /* Waits until HSI48 is stable. */ - -#endif /* STM32_HSI48_ENABLED == TRUE */ - - /* CSI activation.*/ -#if STM32_CSI_ENABLED == TRUE - RCC->CR |= RCC_CR_CSION; - while ((RCC->CR & RCC_CR_CSIRDY) == 0) - ; /* Waits until CSI is stable. */ -#endif /* STM32_CSI_ENABLED == TRUE */ - - /* LSI activation.*/ -#if STM32_LSI_ENABLED == TRUE - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif /* STM32_LSI_ENABLED == TRUE */ - - /* PLLs activation, it happens in parallel in order to - reduce boot time.*/ -#if (STM32_PLL1_ENABLED == TRUE) || \ - (STM32_PLL2_ENABLED == TRUE) || \ - (STM32_PLL3_ENABLED == TRUE) - { - uint32_t onmask = 0; - uint32_t rdymask = 0; - uint32_t cfgmask = 0; - - RCC->PLLCKSELR = RCC_PLLCKSELR_DIVM3_VALUE(STM32_PLL3_DIVM_VALUE) | - RCC_PLLCKSELR_DIVM2_VALUE(STM32_PLL2_DIVM_VALUE) | - RCC_PLLCKSELR_DIVM1_VALUE(STM32_PLL1_DIVM_VALUE) | - RCC_PLLCKSELR_PLLSRC_VALUE(STM32_PLLSRC); - - cfgmask = STM32_PLLCFGR_PLL3RGE | STM32_PLLCFGR_PLL3VCOSEL | RCC_PLLCFGR_PLL3FRACEN | - STM32_PLLCFGR_PLL2RGE | STM32_PLLCFGR_PLL2VCOSEL | RCC_PLLCFGR_PLL2FRACEN | - STM32_PLLCFGR_PLL1RGE | STM32_PLLCFGR_PLL1VCOSEL | RCC_PLLCFGR_PLL1FRACEN; - -#if STM32_PLL1_ENABLED == TRUE - RCC->PLL1FRACR = STM32_PLL1_FRACN; - RCC->PLL1DIVR = STM32_PLL1_DIVR | STM32_PLL1_DIVQ | - STM32_PLL1_DIVP | STM32_PLL1_DIVN; - onmask |= RCC_CR_PLL1ON; - rdymask |= RCC_CR_PLL1RDY; -#if STM32_PLL1_P_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVP1EN; -#endif -#if STM32_PLL1_Q_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVQ1EN; -#endif -#if STM32_PLL1_R_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVR1EN; -#endif -#endif /* STM32_PLL1_ENABLED == TRUE */ - -#if STM32_PLL2_ENABLED == TRUE - RCC->PLL2FRACR = STM32_PLL2_FRACN; - RCC->PLL2DIVR = STM32_PLL2_DIVR | STM32_PLL2_DIVQ | - STM32_PLL2_DIVP | STM32_PLL2_DIVN; - onmask |= RCC_CR_PLL2ON; - rdymask |= RCC_CR_PLL2RDY; -#if STM32_PLL2_P_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVP2EN; -#endif -#if STM32_PLL2_Q_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVQ2EN; -#endif -#if STM32_PLL2_R_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVR2EN; -#endif -#endif /* STM32_PLL2_ENABLED == TRUE */ - -#if STM32_PLL3_ENABLED == TRUE - RCC->PLL3FRACR = STM32_PLL3_FRACN; - RCC->PLL3DIVR = STM32_PLL3_DIVR | STM32_PLL3_DIVQ | - STM32_PLL3_DIVP | STM32_PLL3_DIVN; - onmask |= RCC_CR_PLL3ON; - rdymask |= RCC_CR_PLL3RDY; -#if STM32_PLL3_P_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVP3EN; -#endif -#if STM32_PLL3_Q_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVQ3EN; -#endif -#if STM32_PLL3_R_ENABLED == TRUE - cfgmask |= RCC_PLLCFGR_DIVR3EN; -#endif -#endif /* STM32_PLL3_ENABLED == TRUE */ - - /* Activating enabled PLLs and waiting for all of them to become ready.*/ - RCC->PLLCFGR = cfgmask & STM32_PLLCFGR_MASK; - RCC->CR |= onmask; - while ((RCC->CR & rdymask) != rdymask) - ; - } -#endif /* STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED */ - - /* AHB and APB dividers.*/ - RCC->D1CFGR = STM32_D1CPRE | STM32_D1PPRE3 | STM32_D1HPRE; - RCC->D2CFGR = STM32_D2PPRE2 | STM32_D2PPRE1; - RCC->D3CFGR = STM32_D3PPRE4; - - /* Peripherals clocks.*/ - RCC->D1CCIPR = STM32_CKPERSEL | STM32_SDMMCSEL | STM32_QSPISEL | - STM32_FMCSEL; - RCC->D2CCIP1R = STM32_SWPSEL | STM32_FDCANSEL | STM32_DFSDM1SEL | - STM32_SPDIFSEL | STM32_SPDIFSEL | STM32_SPI45SEL | - STM32_SPI123SEL | STM32_SAI23SEL | STM32_SAI1SEL; - RCC->D2CCIP2R = STM32_LPTIM1SEL | STM32_CECSEL | STM32_USBSEL | - STM32_I2C123SEL | STM32_RNGSEL | STM32_USART16SEL | - STM32_USART234578SEL; - RCC->D3CCIPR = STM32_SPI6SEL | STM32_SAI4BSEL | STM32_SAI4ASEL | - STM32_ADCSEL | STM32_LPTIM345SEL | STM32_LPTIM2SEL | - STM32_I2C4SEL | STM32_LPUART1SEL; - - /* Flash setup.*/ - FLASH->ACR = FLASH_ACR_WRHIGHFREQ_1 | FLASH_ACR_WRHIGHFREQ_0 | - STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY)) { - } - - /* Switching to the configured clock source if it is different - from HSI.*/ -#if STM32_SW != STM32_SW_HSI_CK - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 3U)) - ; -#endif - -#if 0 - /* Peripheral clock sources.*/ - RCC->DCKCFGR2 = STM32_SDMMCSEL | STM32_CK48MSEL | STM32_CECSEL | - STM32_LPTIM1SEL | STM32_I2C4SEL | STM32_I2C3SEL | - STM32_I2C2SEL | STM32_I2C1SEL | STM32_UART8SEL | - STM32_UART7SEL | STM32_USART6SEL | STM32_UART5SEL | - STM32_UART4SEL | STM32_USART3SEL | STM32_USART2SEL | - STM32_USART1SEL; -#endif - - /* RAM1 2 and 3 clocks enabled.*/ - rccEnableSRAM1(true); - rccEnableSRAM2(true); - rccEnableSRAM3(true); -#endif /* STM32_NO_INIT */ -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32H7xx/hal_lld.c + * @brief STM32H7xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f7xx.h. + */ +uint32_t SystemCoreClock = STM32_CORE_CK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static inline void init_bkp_domain(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR1 |= PWR_CR1_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->BDCR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ +} + +/** + * @brief Initializes the PWR unit. + */ +static inline void init_pwr(void) { +#if 0 + PWR_TypeDef *pwr = PWR; /* For inspection.*/ + (void)pwr; +#endif + + /* Lower C3 byte, it must be programmed at very first, then waiting for + power supply to stabilize.*/ + PWR->CR3 = STM32_PWR_CR3 & 0x000000FFU; + while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0) + ; /* CHTODO timeout handling.*/ + + PWR->CR1 = STM32_PWR_CR1 | 0xF0000000U; + PWR->CR2 = STM32_PWR_CR2; + PWR->CR3 = STM32_PWR_CR3; /* Other bits, lower byte is not changed. */ + PWR->CPUCR = STM32_PWR_CPUCR; + PWR->D3CR = STM32_VOS; +#if !defined(STM32_ENFORCE_H7_REV_XY) + SYSCFG->PWRCR = STM32_ODEN; +#endif + while ((PWR->D3CR & PWR_D3CR_VOSRDY) == 0) + ; /* CHTODO timeout handling.*/ +#if STM32_PWR_CR2 & PWR_CR2_BREN +// while ((PWR->CR2 & PWR_CR2_BRRDY) == 0) +// ; +// rccEnableBKPRAM(true); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + +#if STM32_NO_INIT == FALSE + /* Reset of all peripherals. AHB3 is not reset entirely because FMC could + have been initialized in the board initialization file (board.c). + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~0); + rccResetAHB2(~0); + rccResetAHB3(~(RCC_AHB3RSTR_FMCRST | + 0x80000000U)); /* Was RCC_AHB3RSTR_CPURST in Rev-V.*/ + rccResetAHB4(~(RCC_APB4RSTR_SYSCFGRST | STM32_GPIO_EN_MASK)); + rccResetAPB1L(~0); + rccResetAPB1H(~0); + rccResetAPB2(~0); + rccResetAPB3(~0); + rccResetAPB4(~0); +#endif /* STM32_NO_INIT == FALSE */ + + /* DMA subsystems initialization.*/ +#if defined(STM32_BDMA_REQUIRED) + bdmaInit(); +#endif +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif +#if defined(STM32_MDMA_REQUIRED) + mdmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* MPU initialization.*/ +#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) || (STM32_NOCACHE_SRAM3 == TRUE) + { + uint32_t base, size; + +#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == TRUE) + base = 0x30000000U; + size = MPU_RASR_SIZE_512K; +#elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == FALSE) + base = 0x30000000U; + size = MPU_RASR_SIZE_256K; +#elif (STM32_NOCACHE_SRAM1_SRAM2 == FALSE) && (STM32_NOCACHE_SRAM3 == TRUE) + base = 0x30040000U; + size = MPU_RASR_SIZE_16K; +#else +#error "invalid constants used in mcuconf.h" +#endif + + /* The SRAM2 bank can optionally made a non cache-able area for use by + DMA engines.*/ + mpuConfigureRegion(STM32_NOCACHE_MPU_REGION, + base, + MPU_RASR_ATTR_AP_RW_RW | + MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_ATTR_S | + size | + MPU_RASR_ENABLE); + mpuEnable(MPU_CTRL_PRIVDEFENA); + + /* Invalidating data cache to make sure that the MPU settings are taken + immediately.*/ + SCB_CleanInvalidateDCache(); + } +#endif +} + +/** + * @brief STM32H7xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { +#if STM32_NO_INIT == FALSE + uint32_t cfgr; + +#if 0 + RCC_TypeDef *rcc = RCC; /* For inspection.*/ + (void)rcc; +#endif + +#if defined(STM32_ENFORCE_H7_REV_XY) + /* Fix for errata 2.2.15: Reading from AXI SRAM might lead to data + read corruption. + AXI->TARG7_FN_MOD.*/ + *((volatile uint32_t *)(0x51000000 + 0x1108 + 0x7000)) = 0x00000001U; +#endif + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB4(RCC_APB4ENR_SYSCFGEN, true); + + /* PWR initialization.*/ + init_pwr(); + + /* Backup domain initialization.*/ + init_bkp_domain(); + + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + + /* HSI is selected as new source without touching the other fields in + CFGR. This is only required when using a debugger than can cause + restarts.*/ + RCC->CFGR = 0x00000000U; /* Reset SW to HSI. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Wait until HSI is selected. */ + + /* Registers cleared to reset values.*/ + RCC->CR = RCC_CR_HSION; /* CR Reset value. */ + RCC->HSICFGR = 0x40000000U; /* HSICFGR Reset value. */ +#if !defined(STM32_ENFORCE_H7_REV_XY) + RCC->CSICFGR = 0x20000000U; /* CSICFGR Reset value. */ +#endif + RCC->CSR = 0x00000000U; /* CSR reset value. */ + RCC->PLLCFGR = 0x01FF0000U; /* PLLCFGR reset value. */ + + /* Other clock-related settings, done before other things because + recommended in the RM.*/ + cfgr = STM32_MCO2SEL | RCC_CFGR_MCO2PRE_VALUE(STM32_MCO2PRE_VALUE) | + STM32_MCO1SEL | RCC_CFGR_MCO1PRE_VALUE(STM32_MCO1PRE_VALUE) | + RCC_CFGR_RTCPRE_VALUE(STM32_RTCPRE_VALUE) | + STM32_HRTIMSEL | STM32_STOPKERWUCK | STM32_STOPWUCK; +#if STM32_TIMPRE_ENABLE == TRUE + cfgr |= RCC_CFGR_TIMPRE; +#endif + RCC->CFGR = cfgr; + + /* HSE activation with optional bypass.*/ +#if STM32_HSE_ENABLED == TRUE +#if defined(STM32_HSE_BYPASS) + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + RCC->CR |= RCC_CR_HSEON; +#endif + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Waits until HSE is stable. */ +#endif /* STM32_HSE_ENABLED == TRUE */ + + /* HSI48 activation.*/ +#if STM32_HSI48_ENABLED == TRUE + RCC->CR |= RCC_CR_HSI48ON; + while ((RCC->CR & RCC_CR_HSI48RDY) == 0) + ; /* Waits until HSI48 is stable. */ + +#endif /* STM32_HSI48_ENABLED == TRUE */ + + /* CSI activation.*/ +#if STM32_CSI_ENABLED == TRUE + RCC->CR |= RCC_CR_CSION; + while ((RCC->CR & RCC_CR_CSIRDY) == 0) + ; /* Waits until CSI is stable. */ +#endif /* STM32_CSI_ENABLED == TRUE */ + + /* LSI activation.*/ +#if STM32_LSI_ENABLED == TRUE + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif /* STM32_LSI_ENABLED == TRUE */ + + /* PLLs activation, it happens in parallel in order to + reduce boot time.*/ +#if (STM32_PLL1_ENABLED == TRUE) || \ + (STM32_PLL2_ENABLED == TRUE) || \ + (STM32_PLL3_ENABLED == TRUE) + { + uint32_t onmask = 0; + uint32_t rdymask = 0; + uint32_t cfgmask = 0; + + RCC->PLLCKSELR = RCC_PLLCKSELR_DIVM3_VALUE(STM32_PLL3_DIVM_VALUE) | + RCC_PLLCKSELR_DIVM2_VALUE(STM32_PLL2_DIVM_VALUE) | + RCC_PLLCKSELR_DIVM1_VALUE(STM32_PLL1_DIVM_VALUE) | + RCC_PLLCKSELR_PLLSRC_VALUE(STM32_PLLSRC); + + cfgmask = STM32_PLLCFGR_PLL3RGE | STM32_PLLCFGR_PLL3VCOSEL | RCC_PLLCFGR_PLL3FRACEN | + STM32_PLLCFGR_PLL2RGE | STM32_PLLCFGR_PLL2VCOSEL | RCC_PLLCFGR_PLL2FRACEN | + STM32_PLLCFGR_PLL1RGE | STM32_PLLCFGR_PLL1VCOSEL | RCC_PLLCFGR_PLL1FRACEN; + +#if STM32_PLL1_ENABLED == TRUE + RCC->PLL1FRACR = STM32_PLL1_FRACN; + RCC->PLL1DIVR = STM32_PLL1_DIVR | STM32_PLL1_DIVQ | + STM32_PLL1_DIVP | STM32_PLL1_DIVN; + onmask |= RCC_CR_PLL1ON; + rdymask |= RCC_CR_PLL1RDY; +#if STM32_PLL1_P_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVP1EN; +#endif +#if STM32_PLL1_Q_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVQ1EN; +#endif +#if STM32_PLL1_R_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVR1EN; +#endif +#endif /* STM32_PLL1_ENABLED == TRUE */ + +#if STM32_PLL2_ENABLED == TRUE + RCC->PLL2FRACR = STM32_PLL2_FRACN; + RCC->PLL2DIVR = STM32_PLL2_DIVR | STM32_PLL2_DIVQ | + STM32_PLL2_DIVP | STM32_PLL2_DIVN; + onmask |= RCC_CR_PLL2ON; + rdymask |= RCC_CR_PLL2RDY; +#if STM32_PLL2_P_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVP2EN; +#endif +#if STM32_PLL2_Q_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVQ2EN; +#endif +#if STM32_PLL2_R_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVR2EN; +#endif +#endif /* STM32_PLL2_ENABLED == TRUE */ + +#if STM32_PLL3_ENABLED == TRUE + RCC->PLL3FRACR = STM32_PLL3_FRACN; + RCC->PLL3DIVR = STM32_PLL3_DIVR | STM32_PLL3_DIVQ | + STM32_PLL3_DIVP | STM32_PLL3_DIVN; + onmask |= RCC_CR_PLL3ON; + rdymask |= RCC_CR_PLL3RDY; +#if STM32_PLL3_P_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVP3EN; +#endif +#if STM32_PLL3_Q_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVQ3EN; +#endif +#if STM32_PLL3_R_ENABLED == TRUE + cfgmask |= RCC_PLLCFGR_DIVR3EN; +#endif +#endif /* STM32_PLL3_ENABLED == TRUE */ + + /* Activating enabled PLLs and waiting for all of them to become ready.*/ + RCC->PLLCFGR = cfgmask & STM32_PLLCFGR_MASK; + RCC->CR |= onmask; + while ((RCC->CR & rdymask) != rdymask) + ; + } +#endif /* STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED */ + + /* AHB and APB dividers.*/ + RCC->D1CFGR = STM32_D1CPRE | STM32_D1PPRE3 | STM32_D1HPRE; + RCC->D2CFGR = STM32_D2PPRE2 | STM32_D2PPRE1; + RCC->D3CFGR = STM32_D3PPRE4; + + /* Peripherals clocks.*/ + RCC->D1CCIPR = STM32_CKPERSEL | STM32_SDMMCSEL | STM32_QSPISEL | + STM32_FMCSEL; + RCC->D2CCIP1R = STM32_SWPSEL | STM32_FDCANSEL | STM32_DFSDM1SEL | + STM32_SPDIFSEL | STM32_SPDIFSEL | STM32_SPI45SEL | + STM32_SPI123SEL | STM32_SAI23SEL | STM32_SAI1SEL; + RCC->D2CCIP2R = STM32_LPTIM1SEL | STM32_CECSEL | STM32_USBSEL | + STM32_I2C123SEL | STM32_RNGSEL | STM32_USART16SEL | + STM32_USART234578SEL; + RCC->D3CCIPR = STM32_SPI6SEL | STM32_SAI4BSEL | STM32_SAI4ASEL | + STM32_ADCSEL | STM32_LPTIM345SEL | STM32_LPTIM2SEL | + STM32_I2C4SEL | STM32_LPUART1SEL; + + /* Flash setup.*/ + FLASH->ACR = FLASH_ACR_WRHIGHFREQ_1 | FLASH_ACR_WRHIGHFREQ_0 | + STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY)) { + } + + /* Switching to the configured clock source if it is different + from HSI.*/ +#if STM32_SW != STM32_SW_HSI_CK + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 3U)) + ; +#endif + +#if 0 + /* Peripheral clock sources.*/ + RCC->DCKCFGR2 = STM32_SDMMCSEL | STM32_CK48MSEL | STM32_CECSEL | + STM32_LPTIM1SEL | STM32_I2C4SEL | STM32_I2C3SEL | + STM32_I2C2SEL | STM32_I2C1SEL | STM32_UART8SEL | + STM32_UART7SEL | STM32_USART6SEL | STM32_UART5SEL | + STM32_UART4SEL | STM32_USART3SEL | STM32_USART2SEL | + STM32_USART1SEL; +#endif + + /* RAM1 2 and 3 clocks enabled.*/ + rccEnableSRAM1(true); + rccEnableSRAM2(true); + rccEnableSRAM3(true); +#endif /* STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/hal_lld.h b/os/hal/ports/STM32/STM32H7xx/hal_lld.h index b52766de7f..2cc2d57091 100644 --- a/os/hal/ports/STM32/STM32H7xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32H7xx/hal_lld.h @@ -1,3072 +1,3080 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32H7xx/hal_lld.h - * @brief STM32H7xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * - STM32_VDD (as hundredths of Volt). - * . - * One of the following macros must also be defined: - * - STM32H743xx, STM32H753xx very high-performance MCUs. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32H742xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32H742 Single Core Very High Performance with DSP and FPU" - -#elif defined(STM32H743xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32H743 Single Core Very High Performance with DSP and FPU" - -#elif defined(STM32H753xx) -#define PLATFORM_NAME "STM32H753 Single Core Very High Performance with DSP and FPU" - -#elif defined(STM32H745xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32H745 Dual Core Very High Performance with DSP and FPU" - -#elif defined(STM32H755xx) -#define PLATFORM_NAME "STM32H755 Dual Core Very High Performance with DSP and FPU" - -#elif defined(STM32H747xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32H747 Dual Core Very High Performance with DSP and FPU" - -#elif defined(STM32H757xx) -#define PLATFORM_NAME "STM32H757 Dual Core Very High Performance with DSP and FPU" - -#elif defined(STM32H750xx) -#define PLATFORM_NAME "STM32H750 Value Line Very High Performance with DSP and FPU" - -#else -#error "STM32H7xx device not specified" -#endif -/** @} */ - -/** - * @name Sub-family identifier - */ -#if !defined(STM32H7XX) || defined(__DOXYGEN__) -#define STM32H7XX -#endif -/** @} */ - -#if !defined(STM32_ENFORCE_H7_REV_XY) -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Absolute maximum system clock. - */ -#define STM32_SYSCLK_MAX 480000000 - -/** - * @brief Maximum SYSCLK clock frequency without voltage boost. - */ -#define STM32_SYSCLK_MAX_NOBOOST 400000000 - -/** - * @brief Absolute maximum HCLK clock. - */ -#define STM32_HCLK_MAX (STM32_SYSCLK_MAX / 2) - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 50000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_BYP_MIN 4000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSE_CK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSE_CK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSE_CK_MIN 32768 - -/** - * @brief Minimum PLLs input clock frequency.. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief PLLs input threshold frequency 1. - */ -#define STM32_PLLIN_THRESHOLD1 2000000 - -/** - * @brief PLLs input threshold frequency 2. - */ -#define STM32_PLLIN_THRESHOLD2 4000000 - -/** - * @brief PLLs input threshold frequency 3. - */ -#define STM32_PLLIN_THRESHOLD3 8000000 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MIN 150000000 /* DS says 192, RM says 150. */ - -/** - * @brief Threshold PLLs clock frequency. - */ -#define STM32_PLLVCO_THRESHOLD 420000000 - -/** - * @brief Maximum PLLs VCOH clock frequency. - */ -#define STM32_PLLVCO_MAX 960000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX (STM32_HCLK_MAX / 2) - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX (STM32_HCLK_MAX / 2) - -/** - * @brief Maximum APB3 clock frequency. - */ -#define STM32_PCLK3_MAX (STM32_HCLK_MAX / 2) - -/** - * @brief Maximum APB4 clock frequency. - */ -#define STM32_PCLK4_MAX (STM32_HCLK_MAX / 2) - -/** - * @brief Maximum SPI1, SPI2 and SPI3 clock frequency. - */ -#define STM32_SPI123_MAX 200000000 - -/** - * @brief Maximum SPI4, SPI5 and SPI6 clock frequency. - */ -#define STM32_SPI456_MAX 125000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 50000000 -/** @} */ - -#else /* defined(STM32_ENFORCE_H7_REV_XY) */ - -#define STM32_SYSCLK_MAX 400000000 -#define STM32_SYSCLK_MAX_NOBOOST 400000000 -#define STM32_HCLK_MAX (STM32_SYSCLK_MAX / 2) -#define STM32_HSECLK_MAX 48000000 -#define STM32_HSECLK_BYP_MAX 50000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 4000000 -#define STM32_LSE_CK_MAX 32768 -#define STM32_LSE_CK_BYP_MAX 1000000 -#define STM32_LSE_CK_MIN 32768 -#define STM32_PLLIN_MIN 1000000 -#define STM32_PLLIN_THRESHOLD1 2000000 -#define STM32_PLLIN_THRESHOLD2 4000000 -#define STM32_PLLIN_THRESHOLD3 8000000 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLVCO_MIN 150000000 -#define STM32_PLLVCO_THRESHOLD 420000000 -#define STM32_PLLVCO_MAX 836000000 -#define STM32_PCLK1_MAX (STM32_HCLK_MAX / 2) -#define STM32_PCLK2_MAX (STM32_HCLK_MAX / 2) -#define STM32_PCLK3_MAX (STM32_HCLK_MAX / 2) -#define STM32_PCLK4_MAX (STM32_HCLK_MAX / 2) -#define STM32_SPI123_MAX 133000000 -#define STM32_SPI456_MAX 100000000 -#define STM32_ADCCLK_MAX 36000000 - -#endif /* defined(STM32_ENFORCE_H7_REV_XY) */ - -/** - * @name Internal clock sources frequencies - * @{ - */ -#define STM32_HSI_OSC 64000000 -#define STM32_HSI48_OSC 48000000 -#define STM32_CSI_OSC 4000000 -#define STM32_LSI_OSC 32000 -/** @} */ - -/** - * @name Register helpers not found in ST headers - * @{ - */ -#define RCC_CR_HSIDIV_VALUE(n) ((n) << 3U) - -#define RCC_CFGR_SW_VALUE(n) ((n) << 0U) -#define RCC_CFGR_RTCPRE_VALUE(n) ((n) << 8U) -#define RCC_CFGR_MCO1PRE_VALUE(n) ((n) << 18U) -#define RCC_CFGR_MCO1_VALUE(n) ((n) << 22U) -#define RCC_CFGR_MCO2PRE_VALUE(n) ((n) << 25U) -#define RCC_CFGR_MCO2_VALUE(n) ((n) << 29U) - -#define RCC_D1CFGR_D1HPRE_VALUE(n) ((n) << RCC_D1CFGR_HPRE_Pos) -#define RCC_D1CFGR_D1CPRE_VALUE(n) ((n) << RCC_D1CFGR_D1CPRE_Pos) -#define RCC_D1CFGR_D1PPRE3_VALUE(n) ((n) << RCC_D1CFGR_D1PPRE_Pos) - -#define RCC_D2CFGR_D2PPRE1_VALUE(n) ((n) << RCC_D2CFGR_D2PPRE1_Pos) -#define RCC_D2CFGR_D2PPRE2_VALUE(n) ((n) << RCC_D2CFGR_D2PPRE2_Pos) - -#define RCC_D3CFGR_D3PPRE4_VALUE(n) ((n) << RCC_D3CFGR_D3PPRE_Pos) - -#define RCC_PLLCKSELR_PLLSRC_VALUE(n) ((n) << RCC_PLLCKSELR_PLLSRC_Pos) - -#define RCC_PLLCKSELR_DIVM1_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM1_Pos) -#define RCC_PLLCKSELR_DIVM2_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM2_Pos) -#define RCC_PLLCKSELR_DIVM3_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM3_Pos) - -#define RCC_PLL1DIVR_DIVN1_VALUE(n) ((n) << RCC_PLL1DIVR_N1) -#define RCC_PLL1DIVR_DIVP1_VALUE(n) ((n) << RCC_PLL1DIVR_P1) -#define RCC_PLL1DIVR_DIVQ1_VALUE(n) ((n) << RCC_PLL1DIVR_Q1) -#define RCC_PLL1DIVR_DIVR1_VALUE(n) ((n) << RCC_PLL1DIVR_R1) - -#define RCC_PLL1FRACR_FRACN1_VALUE(n) ((n) << RCC_PLL1FRACR_FRACN1_Pos) - -#define RCC_PLL2DIVR_DIVN2_VALUE(n) ((n) << RCC_PLL2DIVR_N2) -#define RCC_PLL2DIVR_DIVP2_VALUE(n) ((n) << RCC_PLL2DIVR_P2) -#define RCC_PLL2DIVR_DIVQ2_VALUE(n) ((n) << RCC_PLL2DIVR_Q2) -#define RCC_PLL2DIVR_DIVR2_VALUE(n) ((n) << RCC_PLL2DIVR_R2) - -#define RCC_PLL2FRACR_FRACN2_VALUE(n) ((n) << RCC_PLL2FRACR_FRACN2_Pos) - -#define RCC_PLL3DIVR_DIVN3_VALUE(n) ((n) << RCC_PLL3DIVR_N3) -#define RCC_PLL3DIVR_DIVP3_VALUE(n) ((n) << RCC_PLL3DIVR_P3) -#define RCC_PLL3DIVR_DIVQ3_VALUE(n) ((n) << RCC_PLL3DIVR_Q3) -#define RCC_PLL3DIVR_DIVR3_VALUE(n) ((n) << RCC_PLL3DIVR_R3) - -#define RCC_PLL3FRACR_FRACN3_VALUE(n) ((n) << RCC_PLL3FRACR_FRACN3_Pos) - -#define RCC_D1CCIPR_CKPERSEL_VALUE(n) ((n) << RCC_D1CCIPR_CKPERSEL_Pos) -#define RCC_D1CCIPR_SDMMCSEL_VALUE(n) ((n) << RCC_D1CCIPR_SDMMCSEL_Pos) -#define RCC_D1CCIPR_QSPISEL_VALUE(n) ((n) << RCC_D1CCIPR_QSPISEL_Pos) -#define RCC_D1CCIPR_FMCSEL_VALUE(n) ((n) << RCC_D1CCIPR_FMCSEL_Pos) - -#define RCC_D2CCIP1R_SWPSEL_VALUE(n) ((n) << RCC_D2CCIP1R_SWPSEL_Pos) -#define RCC_D2CCIP1R_FDCANSEL_VALUE(n) ((n) << RCC_D2CCIP1R_FDCANSEL_Pos) -#define RCC_D2CCIP1R_DFSDM1SEL_VALUE(n) ((n) << RCC_D2CCIP1R_DFSDM1SEL_Pos) -#define RCC_D2CCIP1R_SPDIFSEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPDIFSEL_Pos) -#define RCC_D2CCIP1R_SPI45SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPI45SEL_Pos) -#define RCC_D2CCIP1R_SPI123SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPI123SEL_Pos) -#define RCC_D2CCIP1R_SAI23SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SAI23SEL_Pos) -#define RCC_D2CCIP1R_SAI1SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SAI1SEL_Pos) - -#define RCC_D2CCIP2R_LPTIM1SEL_VALUE(n) ((n) << RCC_D2CCIP2R_LPTIM1SEL_Pos) -#define RCC_D2CCIP2R_CECSEL_VALUE(n) ((n) << RCC_D2CCIP2R_CECSEL_Pos) -#define RCC_D2CCIP2R_USBSEL_VALUE(n) ((n) << RCC_D2CCIP2R_USBSEL_Pos) -#define RCC_D2CCIP2R_I2C123SEL_VALUE(n) ((n) << RCC_D2CCIP2R_I2C123SEL_Pos) -#define RCC_D2CCIP2R_RNGSEL_VALUE(n) ((n) << RCC_D2CCIP2R_RNGSEL_Pos) -#define RCC_D2CCIP2R_USART16SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART16SEL_Pos) -#define RCC_D2CCIP2R_USART234578SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART28SEL_Pos) - -#define RCC_D3CCIPR_SPI6SEL_VALUE(n) ((n) << RCC_D3CCIPR_SPI6SEL_Pos) -#define RCC_D3CCIPR_SAI4BSEL_VALUE(n) ((n) << RCC_D3CCIPR_SAI4BSEL_Pos) -#define RCC_D3CCIPR_SAI4ASEL_VALUE(n) ((n) << RCC_D3CCIPR_SAI4ASEL_Pos) -#define RCC_D3CCIPR_ADCSEL_VALUE(n) ((n) << RCC_D3CCIPR_ADCSEL_Pos) -#define RCC_D3CCIPR_LPTIM345SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPTIM345SEL_Pos) -#define RCC_D3CCIPR_LPTIM2SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPTIM2SEL_Pos) -#define RCC_D3CCIPR_I2C4SEL_VALUE(n) ((n) << RCC_D3CCIPR_I2C4SEL_Pos) -#define RCC_D3CCIPR_LPUART1SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPUART1SEL_Pos) - -#define RCC_BDCR_RTCSEL_VALUE(n) ((n) << RCC_BDCR_RTCSEL_Pos) -/** @} */ - -/** - * @name Configuration switches to be used in @p mcuconf.h - * @{ - */ -#define STM32_ODEN_DISABLED 0U -#define STM32_ODEN_ENABLED (SYSCFG_PWRCR_ODEN) - -#define STM32_VOS_SCALE3 (PWR_D3CR_VOS_0) -#define STM32_VOS_SCALE2 (PWR_D3CR_VOS_1) -#define STM32_VOS_SCALE1 (PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0) - -#define STM32_SW_HSI_CK RCC_CFGR_SW_VALUE(0U) -#define STM32_SW_CSI_CK RCC_CFGR_SW_VALUE(1U) -#define STM32_SW_HSE_CK RCC_CFGR_SW_VALUE(2U) -#define STM32_SW_PLL1_P_CK RCC_CFGR_SW_VALUE(3U) - -#define STM32_D1CPRE_DIV1 RCC_D1CFGR_D1CPRE_VALUE(0U) -#define STM32_D1CPRE_DIV2 RCC_D1CFGR_D1CPRE_VALUE(8U) -#define STM32_D1CPRE_DIV4 RCC_D1CFGR_D1CPRE_VALUE(9U) -#define STM32_D1CPRE_DIV8 RCC_D1CFGR_D1CPRE_VALUE(10U) -#define STM32_D1CPRE_DIV16 RCC_D1CFGR_D1CPRE_VALUE(11U) -#define STM32_D1CPRE_DIV64 RCC_D1CFGR_D1CPRE_VALUE(12U) -#define STM32_D1CPRE_DIV128 RCC_D1CFGR_D1CPRE_VALUE(13U) -#define STM32_D1CPRE_DIV256 RCC_D1CFGR_D1CPRE_VALUE(14U) -#define STM32_D1CPRE_DIV512 RCC_D1CFGR_D1CPRE_VALUE(15U) - -#define STM32_D1HPRE_DIV1 RCC_D1CFGR_D1HPRE_VALUE(0U) -#define STM32_D1HPRE_DIV2 RCC_D1CFGR_D1HPRE_VALUE(8U) -#define STM32_D1HPRE_DIV4 RCC_D1CFGR_D1HPRE_VALUE(9U) -#define STM32_D1HPRE_DIV8 RCC_D1CFGR_D1HPRE_VALUE(10U) -#define STM32_D1HPRE_DIV16 RCC_D1CFGR_D1HPRE_VALUE(11U) -#define STM32_D1HPRE_DIV64 RCC_D1CFGR_D1HPRE_VALUE(12U) -#define STM32_D1HPRE_DIV128 RCC_D1CFGR_D1HPRE_VALUE(13U) -#define STM32_D1HPRE_DIV256 RCC_D1CFGR_D1HPRE_VALUE(14U) -#define STM32_D1HPRE_DIV512 RCC_D1CFGR_D1HPRE_VALUE(15U) - -#define STM32_D1PPRE3_DIV1 RCC_D1CFGR_D1PPRE3_VALUE(0U) -#define STM32_D1PPRE3_DIV2 RCC_D1CFGR_D1PPRE3_VALUE(4U) -#define STM32_D1PPRE3_DIV4 RCC_D1CFGR_D1PPRE3_VALUE(5U) -#define STM32_D1PPRE3_DIV8 RCC_D1CFGR_D1PPRE3_VALUE(6U) -#define STM32_D1PPRE3_DIV16 RCC_D1CFGR_D1PPRE3_VALUE(7U) - -#define STM32_D2PPRE1_DIV1 RCC_D2CFGR_D2PPRE1_VALUE(0U) -#define STM32_D2PPRE1_DIV2 RCC_D2CFGR_D2PPRE1_VALUE(4U) -#define STM32_D2PPRE1_DIV4 RCC_D2CFGR_D2PPRE1_VALUE(5U) -#define STM32_D2PPRE1_DIV8 RCC_D2CFGR_D2PPRE1_VALUE(6U) -#define STM32_D2PPRE1_DIV16 RCC_D2CFGR_D2PPRE1_VALUE(7U) - -#define STM32_D2PPRE2_DIV1 RCC_D2CFGR_D2PPRE2_VALUE(0U) -#define STM32_D2PPRE2_DIV2 RCC_D2CFGR_D2PPRE2_VALUE(4U) -#define STM32_D2PPRE2_DIV4 RCC_D2CFGR_D2PPRE2_VALUE(5U) -#define STM32_D2PPRE2_DIV8 RCC_D2CFGR_D2PPRE2_VALUE(6U) -#define STM32_D2PPRE2_DIV16 RCC_D2CFGR_D2PPRE2_VALUE(7U) - -#define STM32_D3PPRE4_DIV1 RCC_D3CFGR_D3PPRE4_VALUE(0U) -#define STM32_D3PPRE4_DIV2 RCC_D3CFGR_D3PPRE4_VALUE(4U) -#define STM32_D3PPRE4_DIV4 RCC_D3CFGR_D3PPRE4_VALUE(5U) -#define STM32_D3PPRE4_DIV8 RCC_D3CFGR_D3PPRE4_VALUE(6U) -#define STM32_D3PPRE4_DIV16 RCC_D3CFGR_D3PPRE4_VALUE(7U) - -#define STM32_HSIDIV_DIV1 RCC_CR_HSIDIV_VALUE(0U) -#define STM32_HSIDIV_DIV2 RCC_CR_HSIDIV_VALUE(1U) -#define STM32_HSIDIV_DIV4 RCC_CR_HSIDIV_VALUE(2U) -#define STM32_HSIDIV_DIV8 RCC_CR_HSIDIV_VALUE(3U) - -#define STM32_MCO1SEL_HSI_CK RCC_CFGR_MCO1_VALUE(0U) -#define STM32_MCO1SEL_LSE_CK RCC_CFGR_MCO1_VALUE(1U) -#define STM32_MCO1SEL_HSE_CK RCC_CFGR_MCO1_VALUE(2U) -#define STM32_MCO1SEL_PLL1_Q_CK RCC_CFGR_MCO1_VALUE(3U) -#define STM32_MCO1SEL_HSI48_CK RCC_CFGR_MCO1_VALUE(4U) - -#define STM32_MCO2SEL_SYS_CK RCC_CFGR_MCO2_VALUE(0U) -#define STM32_MCO2SEL_PLL2_P_CK RCC_CFGR_MCO2_VALUE(1U) -#define STM32_MCO2SEL_HSE_CK RCC_CFGR_MCO2_VALUE(2U) -#define STM32_MCO2SEL_PLL1_P_CK RCC_CFGR_MCO2_VALUE(3U) -#define STM32_MCO2SEL_CSI_CK RCC_CFGR_MCO2_VALUE(4U) -#define STM32_MCO2SEL_LSI_CK RCC_CFGR_MCO2_VALUE(5U) - -#define STM32_RTCSEL_MASK RCC_BDCR_RTCSEL_Msk -#define STM32_RTCSEL_NOCLK RCC_BDCR_RTCSEL_VALUE(0U) -#define STM32_RTCSEL_LSE_CK RCC_BDCR_RTCSEL_VALUE(1U) -#define STM32_RTCSEL_LSI_CK RCC_BDCR_RTCSEL_VALUE(2U) -#define STM32_RTCSEL_HSE_1M_CK RCC_BDCR_RTCSEL_VALUE(3U) - -#define STM32_HRTIMSEL_C_CLK RCC_CFGR_HRTIMSEL - -#define STM32_STOPKERWUCK_ENABLED RCC_CFGR_STOPKERWUCK - -#define STM32_STOPWUCK_ENABLED RCC_CFGR_STOPKERWUCK - -#define STM32_PLLSRC_HSI_CK RCC_PLLCKSELR_PLLSRC_VALUE(0U) -#define STM32_PLLSRC_CSI_CK RCC_PLLCKSELR_PLLSRC_VALUE(1U) -#define STM32_PLLSRC_HSE_CK RCC_PLLCKSELR_PLLSRC_VALUE(2U) -#define STM32_PLLSRC_DISABLE RCC_PLLCKSELR_PLLSRC_VALUE(23U) - -#define STM32_CKPERSEL_HSI_CK RCC_D1CCIPR_CKPERSEL_VALUE(0U) -#define STM32_CKPERSEL_CSI_CK RCC_D1CCIPR_CKPERSEL_VALUE(1U) -#define STM32_CKPERSEL_HSE_CK RCC_D1CCIPR_CKPERSEL_VALUE(2U) - -#define STM32_SDMMCSEL_PLL1_Q_CK RCC_D1CCIPR_SDMMCSEL_VALUE(0U) -#define STM32_SDMMCSEL_PLL2_R_CK RCC_D1CCIPR_SDMMCSEL_VALUE(1U) - -#define STM32_QSPISEL_HCLK RCC_D1CCIPR_QSPISEL_VALUE(0U) -#define STM32_QSPISEL_PLL1_Q_CK RCC_D1CCIPR_QSPISEL_VALUE(1U) -#define STM32_QSPISEL_PLL2_R_CK RCC_D1CCIPR_QSPISEL_VALUE(2U) -#define STM32_QSPISEL_PER_CK RCC_D1CCIPR_QSPISEL_VALUE(3U) - -#define STM32_FMCSEL_HCLK RCC_D1CCIPR_FMCSEL_VALUE(0U) -#define STM32_FMCSEL_PLL1_Q_CK RCC_D1CCIPR_FMCSEL_VALUE(1U) -#define STM32_FMCSEL_PLL2_R_CK RCC_D1CCIPR_FMCSEL_VALUE(2U) -#define STM32_FMCSEL_PER_CK RCC_D1CCIPR_FMCSEL_VALUE(3U) - -#define STM32_SWPSEL_PCLK1 RCC_D2CCIP1R_SWPSEL_VALUE(0U) -#define STM32_SWPSEL_HSI_KER_CK RCC_D2CCIP1R_SWPSEL_VALUE(1U) - -#define STM32_FDCANSEL_HSE_CK RCC_D2CCIP1R_FDCANSEL_VALUE(0U) -#define STM32_FDCANSEL_PLL1_Q_CK RCC_D2CCIP1R_FDCANSEL_VALUE(1U) -#define STM32_FDCANSEL_PLL2_Q_CK RCC_D2CCIP1R_FDCANSEL_VALUE(2U) - -#define STM32_DFSDM1SEL_PCLK2 RCC_D2CCIP1R_DFSDM1SEL_VALUE(0U) -#define STM32_DFSDM1SEL_SYS_CK RCC_D2CCIP1R_DFSDM1SEL_VALUE(1U) - -#define STM32_SPDIFSEL_PLL1_Q_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(0U) -#define STM32_SPDIFSEL_PLL2_R_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(1U) -#define STM32_SPDIFSEL_PLL3_R_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(2U) -#define STM32_SPDIFSEL_HSI_KET_CLK RCC_D2CCIP1R_SPDIFSEL_VALUE(3U) - -#define STM32_SPI45SEL_PCLK2 RCC_D2CCIP1R_SPI45SEL_VALUE(0U) -#define STM32_SPI45SEL_PLL2_Q_CK RCC_D2CCIP1R_SPI45SEL_VALUE(1U) -#define STM32_SPI45SEL_PLL3_Q_CK RCC_D2CCIP1R_SPI45SEL_VALUE(2U) -#define STM32_SPI45SEL_HSI_KER_CK RCC_D2CCIP1R_SPI45SEL_VALUE(3U) -#define STM32_SPI45SEL_CSI_KER_CK RCC_D2CCIP1R_SPI45SEL_VALUE(4U) -#define STM32_SPI45SEL_HSE_CK RCC_D2CCIP1R_SPI45SEL_VALUE(5U) - -#define STM32_SPI123SEL_PLL1_Q_CK RCC_D2CCIP1R_SPI123SEL_VALUE(0U) -#define STM32_SPI123SEL_PLL2_P_CK RCC_D2CCIP1R_SPI123SEL_VALUE(1U) -#define STM32_SPI123SEL_PLL3_P_CK RCC_D2CCIP1R_SPI123SEL_VALUE(2U) -#define STM32_SPI123SEL_I2S_CKIN RCC_D2CCIP1R_SPI123SEL_VALUE(3U) -#define STM32_SPI123SEL_PER_CK RCC_D2CCIP1R_SPI123SEL_VALUE(4U) - -#define STM32_SAI23SEL_PLL1_Q_CK RCC_D2CCIP1R_SAI23SEL_VALUE(0U) -#define STM32_SAI23SEL_PLL2_P_CK RCC_D2CCIP1R_SAI23SEL_VALUE(1U) -#define STM32_SAI23SEL_PLL3_P_CK RCC_D2CCIP1R_SAI23SEL_VALUE(2U) -#define STM32_SAI23SEL_I2S_CKIN RCC_D2CCIP1R_SAI23SEL_VALUE(3U) -#define STM32_SAI23SEL_PER_CK RCC_D2CCIP1R_SAI23SEL_VALUE(4U) - -#define STM32_SAI1SEL_PLL1_Q_CK RCC_D2CCIP1R_SAI1SEL_VALUE(0U) -#define STM32_SAI1SEL_PLL2_P_CK RCC_D2CCIP1R_SAI1SEL_VALUE(1U) -#define STM32_SAI1SEL_PLL3_P_CK RCC_D2CCIP1R_SAI1SEL_VALUE(2U) -#define STM32_SAI1SEL_I2S_CKIN RCC_D2CCIP1R_SAI1SEL_VALUE(3U) -#define STM32_SAI1SEL_PER_CK RCC_D2CCIP1R_SAI1SEL_VALUE(4U) - -#define STM32_LPTIM1SEL_PCLK1 RCC_D2CCIP2R_LPTIM1SEL_VALUE(0U) -#define STM32_LPTIM1SEL_PLL2_P_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(1U) -#define STM32_LPTIM1SEL_PLL3_R_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(2U) -#define STM32_LPTIM1SEL_LSE_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(3U) -#define STM32_LPTIM1SEL_LSI_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(4U) -#define STM32_LPTIM1SEL_PER_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(5U) - -#define STM32_CECSEL_LSE_CK RCC_D2CCIP2R_CECSEL_VALUE(0U) -#define STM32_CECSEL_LSI_CK RCC_D2CCIP2R_CECSEL_VALUE(1U) -#define STM32_CECSEL_CSI_KER_CK RCC_D2CCIP2R_CECSEL_VALUE(2U) -#define STM32_CECSEL_DISABLE RCC_D2CCIP2R_CECSEL_VALUE(3U) - -#define STM32_USBSEL_DISABLE RCC_D2CCIP2R_USBSEL_VALUE(0U) -#define STM32_USBSEL_PLL1_Q_CK RCC_D2CCIP2R_USBSEL_VALUE(1U) -#define STM32_USBSEL_PLL3_Q_CK RCC_D2CCIP2R_USBSEL_VALUE(2U) -#define STM32_USBSEL_HSI48_CK RCC_D2CCIP2R_USBSEL_VALUE(3U) - -#define STM32_I2C123SEL_PCLK1 RCC_D2CCIP2R_I2C123SEL_VALUE(0U) -#define STM32_I2C123SEL_PLL3_R_CK RCC_D2CCIP2R_I2C123SEL_VALUE(1U) -#define STM32_I2C123SEL_HSI_KER_CK RCC_D2CCIP2R_I2C123SEL_VALUE(2U) -#define STM32_I2C123SEL_CSI_KER_CK RCC_D2CCIP2R_I2C123SEL_VALUE(3U) - -#define STM32_RNGSEL_HSI48_CK RCC_D2CCIP2R_RNGSEL_VALUE(0U) -#define STM32_RNGSEL_PLL1_Q_CK RCC_D2CCIP2R_RNGSEL_VALUE(1U) -#define STM32_RNGSEL_LSE_CK RCC_D2CCIP2R_RNGSEL_VALUE(2U) -#define STM32_RNGSEL_LSI_CK RCC_D2CCIP2R_RNGSEL_VALUE(3U) - -#define STM32_USART16SEL_PCLK2 RCC_D2CCIP2R_USART16SEL_VALUE(0U) -#define STM32_USART16SEL_PLL2_Q_CK RCC_D2CCIP2R_USART16SEL_VALUE(1U) -#define STM32_USART16SEL_PLL3_Q_CK RCC_D2CCIP2R_USART16SEL_VALUE(2U) -#define STM32_USART16SEL_HSI_KER_CK RCC_D2CCIP2R_USART16SEL_VALUE(3U) -#define STM32_USART16SEL_CSI_KER_CK RCC_D2CCIP2R_USART16SEL_VALUE(4U) -#define STM32_USART16SEL_LSE_CK RCC_D2CCIP2R_USART16SEL_VALUE(5U) - -#define STM32_USART234578SEL_PCLK1 RCC_D2CCIP2R_USART234578SEL_VALUE(0U) -#define STM32_USART234578SEL_PLL2_Q_CK RCC_D2CCIP2R_USART234578SEL_VALUE(1U) -#define STM32_USART234578SEL_PLL3_Q_CK RCC_D2CCIP2R_USART234578SEL_VALUE(2U) -#define STM32_USART234578SEL_HSI_KER_CK RCC_D2CCIP2R_USART234578SEL_VALUE(3U) -#define STM32_USART234578SEL_CSI_KER_CK RCC_D2CCIP2R_USART234578SEL_VALUE(4U) -#define STM32_USART234578SEL_LSE_CK RCC_D2CCIP2R_USART234578SEL_VALUE(5U) - -#define STM32_SPI6SEL_PCLK4 RCC_D3CCIPR_SPI6SEL_VALUE(0U) -#define STM32_SPI6SEL_PLL2_Q_CK RCC_D3CCIPR_SPI6SEL_VALUE(1U) -#define STM32_SPI6SEL_PLL3_Q_CK RCC_D3CCIPR_SPI6SEL_VALUE(2U) -#define STM32_SPI6SEL_HSI_KER_CK RCC_D3CCIPR_SPI6SEL_VALUE(3U) -#define STM32_SPI6SEL_CSI_KER_CK RCC_D3CCIPR_SPI6SEL_VALUE(4U) -#define STM32_SPI6SEL_HSE_CK RCC_D3CCIPR_SPI6SEL_VALUE(5U) - -#define STM32_SAI4BSEL_PLL1_Q_CK RCC_D3CCIPR_SAI4BSEL_VALUE(0U) -#define STM32_SAI4BSEL_PLL2_P_CK RCC_D3CCIPR_SAI4BSEL_VALUE(1U) -#define STM32_SAI4BSEL_PLL3_P_CK RCC_D3CCIPR_SAI4BSEL_VALUE(2U) -#define STM32_SAI4BSEL_I2S_CKIN RCC_D3CCIPR_SAI4BSEL_VALUE(3U) -#define STM32_SAI4BSEL_PER_CK RCC_D3CCIPR_SAI4BSEL_VALUE(4U) - -#define STM32_SAI4ASEL_PLL1_Q_CK RCC_D3CCIPR_SAI4ASEL_VALUE(0U) -#define STM32_SAI4ASEL_PLL2_P_CK RCC_D3CCIPR_SAI4ASEL_VALUE(1U) -#define STM32_SAI4ASEL_PLL3_P_CK RCC_D3CCIPR_SAI4ASEL_VALUE(2U) -#define STM32_SAI4ASEL_I2S_CKIN RCC_D3CCIPR_SAI4ASEL_VALUE(3U) -#define STM32_SAI4ASEL_PER_CK RCC_D3CCIPR_SAI4ASEL_VALUE(4U) - -#define STM32_ADCSEL_PLL2_P_CK RCC_D3CCIPR_ADCSEL_VALUE(0U) -#define STM32_ADCSEL_PLL3_R_CK RCC_D3CCIPR_ADCSEL_VALUE(1U) -#define STM32_ADCSEL_PER_CK RCC_D3CCIPR_ADCSEL_VALUE(2U) -#define STM32_ADCSEL_DISABLE RCC_D3CCIPR_ADCSEL_VALUE(3U) - -#define STM32_LPTIM345SEL_PCLK4 RCC_D3CCIPR_LPTIM345SEL_VALUE(0U) -#define STM32_LPTIM345SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(1U) -#define STM32_LPTIM345SEL_PLL3_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(2U) -#define STM32_LPTIM345SEL_LSE_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(3U) -#define STM32_LPTIM345SEL_LSI_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(4U) -#define STM32_LPTIM345SEL_PER_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(5U) - -#define STM32_LPTIM2SEL_PCLK4 RCC_D3CCIPR_LPTIM2SEL_VALUE(0U) -#define STM32_LPTIM2SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(1U) -#define STM32_LPTIM2SEL_PLL3_P_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(2U) -#define STM32_LPTIM2SEL_LSE_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(3U) -#define STM32_LPTIM2SEL_LSI_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(4U) -#define STM32_LPTIM2SEL_PER_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(5U) - -#define STM32_I2C4SEL_PCLK4 RCC_D3CCIPR_I2C4SEL_VALUE(0U) -#define STM32_I2C4SEL_PLL3_R_CK RCC_D3CCIPR_I2C4SEL_VALUE(1U) -#define STM32_I2C4SEL_HSI_KER_CK RCC_D3CCIPR_I2C4SEL_VALUE(2U) -#define STM32_I2C4SEL_CSI_KER_CK RCC_D3CCIPR_I2C4SEL_VALUE(3U) - -#define STM32_LPUART1SEL_PCLK4 RCC_D3CCIPR_LPUART1SEL_VALUE(0U) -#define STM32_LPUART1SEL_PLL2_Q_CK RCC_D3CCIPR_LPUART1SEL_VALUE(1U) -#define STM32_LPUART1SEL_PLL3_Q_CK RCC_D3CCIPR_LPUART1SEL_VALUE(2U) -#define STM32_LPUART1SEL_HSI_KER_CK RCC_D3CCIPR_LPUART1SEL_VALUE(3U) -#define STM32_LPUART1SEL_CSI_KER_CK RCC_D3CCIPR_LPUART1SEL_VALUE(4U) -#define STM32_LPUART1SEL_LSE_CK RCC_D3CCIPR_LPUART1SEL_VALUE(5U) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - * @note All the clock tree constants are calculated but the initialization - * is not performed. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Target code for this HAL configuration. - * @note Core 1 is the Cortex-M7, core 2 is the Cortex-M4. - */ -#if !defined(STM32_TARGET_CORE) || defined(__DOXYGEN__) -#define STM32_TARGET_CORE 1 -#endif - -/** - * @brief MPU region to be used for no-cache RAM area. - */ -#if !defined(STM32_NOCACHE_MPU_REGION) || defined(__DOXYGEN__) -#define STM32_NOCACHE_MPU_REGION MPU_REGION_6 -#endif - -/** - * @brief Add no-cache attribute to SRAM1 and SRAM2. - * @note MPU region 7 is used if enabled. - */ -#if !defined(STM32_NOCACHE_SRAM1_SRAM2) || defined(__DOXYGEN__) -#define STM32_NOCACHE_SRAM1_SRAM2 FALSE -#endif - -/** - * @brief Add no-cache attribute to SRAM3. - * @note MPU region 7 is used if enabled. - */ -#if !defined(STM32_NOCACHE_SRAM3) || defined(__DOXYGEN__) -#define STM32_NOCACHE_SRAM3 TRUE -#endif - -/** - * @brief PWR CR1 initializer. - */ -#if !defined(STM32_PWR_CR1) || defined(__DOXYGEN__) -#define STM32_PWR_CR1 (PWR_CR1_SVOS_1 | \ - PWR_CR1_SVOS_0) -#endif - -/** - * @brief PWR CR2 initializer. - */ -#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) -#define STM32_PWR_CR2 (PWR_CR2_BREN) -#endif - -/** - * @brief PWR CR3 initializer. - */ -#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__) -#define STM32_PWR_CR3 (PWR_CR3_LDOEN | \ - PWR_CR3_USBREGEN | \ - PWR_CR3_USB33DEN) -#endif - -/** - * @brief PWR CPUCR initializer. - */ -#if !defined(STM32_PWR_CPUCR) || defined(__DOXYGEN__) -#define STM32_PWR_CPUCR 0 -#endif - -/** - * @brief VOS setting. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_SCALE1 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_CSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_CSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSI48 clock source. - */ -#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI48_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED TRUE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief HSI divider. - */ -#if !defined(STM32_HSIDIV) || defined(__DOXYGEN__) -#define STM32_HSIDIV STM32_HSIDIV_DIV1 -#endif - -/** - * @brief Clock source for all PLLs. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE_CK -#endif - -/** - * @brief Masking of PLLCFGR register. - * @note By default all options in PLLCFGR are enabled, this option - * allows to mask specific bits for power saving reasons. - * Use with caution. - */ -#if !defined(STM32_PLLCFGR_MASK) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_MASK ~0 -#endif - -/** - * @brief Enables or disables the PLL1. - */ -#if !defined(STM32_PLL1_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL1_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL1 P output. - */ -#if !defined(STM32_PLL1_P_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL1_P_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL1 Q output. - */ -#if !defined(STM32_PLL1_Q_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL1_Q_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL1 R output. - */ -#if !defined(STM32_PLL1_R_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL1_R_ENABLED TRUE -#endif - -/** - * @brief PLL1 DIVM divider. - * @note The allowed values are 1..63. - */ -#if !defined(STM32_PLL1_DIVM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL1_DIVM_VALUE 4 -#endif - -/** - * @brief PLL1 DIVN multiplier. - * @note The allowed values are 4..512. - */ -#if !defined(STM32_PLL1_DIVN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL1_DIVN_VALUE 400 -#endif - -/** - * @brief PLL1 FRACN multiplier, zero if no fractional part. - * @note The allowed values are 0..8191. - */ -#if !defined(STM32_PLL1_FRACN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL1_FRACN_VALUE 0 -#endif - -/** - * @brief PLL1 DIVP divider. - * @note The allowed values are 2..128, odd values not allowed. - */ -#if !defined(STM32_PLL1_DIVP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL1_DIVP_VALUE 2 -#endif - -/** - * @brief PLL1 DIVQ divider. - * @note The allowed values are 1..128. - */ -#if !defined(STM32_PLL1_DIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL1_DIVQ_VALUE 8 -#endif - -/** - * @brief PLL1 DIVR divider. - * @note The allowed values are 1..128. - */ -#if !defined(STM32_PLL1_DIVR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL1_DIVR_VALUE 8 -#endif - -/** - * @brief Enables or disables the PLL2. - */ -#if !defined(STM32_PLL2_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL2_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL2 P output. - */ -#if !defined(STM32_PLL2_P_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL1_2_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL2 Q output. - */ -#if !defined(STM32_PLL2_Q_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL2_Q_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL2 R output. - */ -#if !defined(STM32_PLL2_R_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL2_R_ENABLED TRUE -#endif - -/** - * @brief PLL2 DIVM divider. - * @note The allowed values are 1..63. - */ -#if !defined(STM32_PLL2_DIVM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2_DIVM_VALUE 4 -#endif - -/** - * @brief PLL2 DIVN multiplier. - * @note The allowed values are 4..512. - */ -#if !defined(STM32_PLL2_DIVN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2_DIVN_VALUE 400 -#endif - -/** - * @brief PLL2 FRACN multiplier, zero if no fractional part. - * @note The allowed values are 0..8191. - */ -#if !defined(STM32_PLL2_FRACN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2_FRACN_VALUE 0 -#endif - -/** - * @brief PLL2 DIVP divider. - * @note The allowed values are 2..128, odd values not allowed. - */ -#if !defined(STM32_PLL2_DIVP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2_DIVP_VALUE 40 -#endif - -/** - * @brief PLL2 DIVQ divider. - * @note The allowed values are 1..128. - */ -#if !defined(STM32_PLL2_DIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2_DIVQ_VALUE 8 -#endif - -/** - * @brief PLL2 DIVR divider. - * @note The allowed values are 1..128. - */ -#if !defined(STM32_PLL2_DIVR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL2_DIVR_VALUE 8 -#endif - -/** - * @brief Enables or disables the PLL3. - */ -#if !defined(STM32_PLL3_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL3_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL3 P output. - */ -#if !defined(STM32_PLL3_P_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL3_P_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL3 Q output. - */ -#if !defined(STM32_PLL3_Q_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL3_Q_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the PLL3 R output. - */ -#if !defined(STM32_PLL3_R_ENABLED) || defined(__DOXYGEN__) -#define STM32_PLL3_R_ENABLED TRUE -#endif - -/** - * @brief PLL3 DIVM divider. - * @note The allowed values are 1..63. - */ -#if !defined(STM32_PLL3_DIVM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3_DIVM_VALUE 4 -#endif - -/** - * @brief PLL3 DIVN multiplier. - * @note The allowed values are 4..512. - */ -#if !defined(STM32_PLL3_DIVN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3_DIVN_VALUE 400 -#endif - -/** - * @brief PLL3 FRACN multiplier, zero if no fractional part. - * @note The allowed values are 0..8191. - */ -#if !defined(STM32_PLL3_FRACN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3_FRACN_VALUE 0 -#endif - -/** - * @brief PLL3 DIVP divider. - * @note The allowed values are 2..128, odd values not allowed. - */ -#if !defined(STM32_PLL3_DIVP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3_DIVP_VALUE 8 -#endif - -/** - * @brief PLL3 DIVQ divider. - * @note The allowed values are 1..128. - */ -#if !defined(STM32_PLL3_DIVQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3_DIVQ_VALUE 8 -#endif - -/** - * @brief PLL3 DIVR divider. - * @note The allowed values are 1..128. - */ -#if !defined(STM32_PLL3_DIVR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLL3_DIVR_VALUE 8 -#endif - -/** - * @brief Peripherals clock selector. - */ -#if !defined(STM32_CKPERSEL) || defined(__DOXYGEN__) -#define STM32_CKPERSEL STM32_CKPERSEL_HSE_CK -#endif - -/** - * @brief MCO1 clock selector. - */ -#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) -#define STM32_MCO1SEL STM32_MCO1SEL_HSI_CK -#endif - -/** - * @brief MCO1 clock prescaler. - */ -#if !defined(STM32_MCO1PRE_VALUE) || defined(__DOXYGEN__) -#define STM32_MCO1PRE_VALUE 4 -#endif - -/** - * @brief MCO2 clock selector. - */ -#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) -#define STM32_MCO2SEL STM32_MCO2SEL_SYS_CK -#endif - -/** - * @brief MCO2 clock prescaler. - */ -#if !defined(STM32_MCO2PRE_VALUE) || defined(__DOXYGEN__) -#define STM32_MCO2PRE_VALUE 4 -#endif - -/** - * @brief TIM clock prescaler selection. - */ -#if !defined(STM32_TIMPRE_ENABLE) || defined(__DOXYGEN__) -#define STM32_TIMPRE_ENABLE FALSE -#endif - -/** - * @brief HRTIM clock prescaler selection. - */ -#if !defined(STM32_HRTIMSEL) || defined(__DOXYGEN__) -#define STM32_HRTIMSEL 0 -#endif - -/** - * @brief Kernel clock selection after a wake up from system Stop. - */ -#if !defined(STM32_STOPKERWUCK) || defined(__DOXYGEN__) -#define STM32_STOPKERWUCK 0 -#endif - -/** - * @brief System clock selection after a wake up from system Stop. - */ -#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) -#define STM32_STOPWUCK 0 -#endif - -/** - * @brief RTC HSE prescaler value. - * @note The allowed values are 2..63. - */ -#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) -#define STM32_RTCPRE_VALUE 8 -#endif - -/** - * @brief Main clock source selection. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL1_P_CK1_P_CK -#endif - -/** - * @brief RTC clock selector. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSE_CK -#endif - -/** - * @brief Clock domain 1 core bus prescaler. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_D1CPRE) || defined(__DOXYGEN__) -#define STM32_D1CPRE STM32_D1CPRE_DIV1 -#endif - -/** - * @brief Clock domain 1 HPRE prescaler. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_D1HPRE) || defined(__DOXYGEN__) -#define STM32_D1HPRE STM32_D1HPRE_DIV4 -#endif - -/** - * @brief Clock domain 1 peripherals bus prescaler. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_D1PPRE3) || defined(__DOXYGEN__) -#define STM32_D1PPRE3 STM32_D1PPRE3_DIV1 -#endif - -/** - * @brief Clock domain 2 peripherals bus 1 prescaler. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_D2PPRE1) || defined(__DOXYGEN__) -#define STM32_D2PPRE1 STM32_D2PPRE1_DIV1 -#endif - -/** - * @brief Clock domain 2 peripherals bus 2 prescaler. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_D2PPRE2) || defined(__DOXYGEN__) -#define STM32_D2PPRE2 STM32_D2PPRE2_DIV1 -#endif - -/** - * @brief Clock domain 3 peripherals bus prescaler. - * @note This setting can be modified at runtime. - */ -#if !defined(STM32_D3PPRE4) || defined(__DOXYGEN__) -#define STM32_D3PPRE4 STM32_D3PPRE4_DIV1 -#endif - -/** - * @brief SDMMC clock source. - */ -#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__) -#define STM32_SDMMCSEL STM32_SDMMCSEL_PLL1_Q_CK -#endif - -/** - * @brief QSPI clock source. - */ -#if !defined(STM32_QSPISEL) || defined(__DOXYGEN__) -#define STM32_QSPISEL STM32_QSPISEL_HCLK -#endif - -/** - * @brief FMC clock source. - */ -#if !defined(STM32_FMCSEL) || defined(__DOXYGEN__) -#define STM32_FMCSEL STM32_QSPISEL_HCLK -#endif - -/** - * @brief SWP clock source. - */ -#if !defined(STM32_SWPSEL) || defined(__DOXYGEN__) -#define STM32_SWPSEL STM32_SWPSEL_PCLK1 -#endif - -/** - * @brief FDCAN clock source. - */ -#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__) -#define STM32_FDCANSEL STM32_FDCANSEL_HSE_CK -#endif - -/** - * @brief DFSDM1 clock source. - */ -#if !defined(STM32_DFSDM1SEL) || defined(__DOXYGEN__) -#define STM32_DFSDM1SEL STM32_DFSDM1SEL_PCLK2 -#endif - -/** - * @brief SPDIF clock source. - */ -#if !defined(STM32_SPDIFSEL) || defined(__DOXYGEN__) -#define STM32_SPDIFSEL STM32_SPDIFSEL_PLL1_Q_CK -#endif - -/** - * @brief SPI45 clock source. - */ -#if !defined(STM32_SPI45SEL) || defined(__DOXYGEN__) -#define STM32_SPI45SEL STM32_SPI45SEL_PCLK2 -#endif - -/** - * @brief SPI123 clock source. - */ -#if !defined(STM32_SPI123SEL) || defined(__DOXYGEN__) -#define STM32_SPI123SEL STM32_SPI123SEL_PLL1_Q_CK -#endif - -/** - * @brief SAI23 clock source. - */ -#if !defined(STM32_SAI23SEL) || defined(__DOXYGEN__) -#define STM32_SAI23SEL STM32_SAI23SEL_PLL1_Q_CK -#endif - -/** - * @brief SAI1 clock source. - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_PLL1_Q_CK -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1_PCLK1 -#endif - -/** - * @brief CEC clock source. - */ -#if !defined(STM32_CECSEL) || defined(__DOXYGEN__) -#define STM32_CECSEL STM32_CECSEL_LSE_CK -#endif - -/** - * @brief USB clock source. - */ -#if !defined(STM32_USBSEL) || defined(__DOXYGEN__) -#define STM32_USBSEL STM32_USBSEL_PLL3_Q_CK -#endif - -/** - * @brief I2C123 clock source. - */ -#if !defined(STM32_I2C123SEL) || defined(__DOXYGEN__) -#define STM32_I2C123SEL STM32_I2C123SEL_PCLK1 -#endif - -/** - * @brief RNG clock source. - */ -#if !defined(STM32_RNGSEL) || defined(__DOXYGEN__) -#define STM32_RNGSEL STM32_RNGSEL_HSI48_CK -#endif - -/** - * @brief USART16 clock source. - */ -#if !defined(STM32_USART16SEL) || defined(__DOXYGEN__) -#define STM32_USART16SEL STM32_USART16SEL_PCLK2 -#endif - -/** - * @brief USART234578 clock source. - */ -#if !defined(STM32_USART234578SEL) || defined(__DOXYGEN__) -#define STM32_USART234578SEL STM32_USART234578SEL_PCLK1 -#endif - -/** - * @brief SPI6SEL clock source. - */ -#if !defined(STM32_SPI6SEL) || defined(__DOXYGEN__) -#define STM32_SPI6SEL STM32_SPI6SEL_PCLK4 -#endif - -/** - * @brief SAI4BSEL clock source. - */ -#if !defined(STM32_SAI4BSEL) || defined(__DOXYGEN__) -#define STM32_SAI4BSEL STM32_SAI4BSEL_PLL1_Q_CK -#endif - -/** - * @brief SAI4ASEL clock source. - */ -#if !defined(STM32_SAI4ASEL) || defined(__DOXYGEN__) -#define STM32_SAI4ASEL STM32_SAI4ASEL_PLL1_Q_CK -#endif - -/** - * @brief ADCSEL clock source. - */ -#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) -#define STM32_ADCSEL STM32_ADCSEL_PLL2_P_CK -#endif - -/** - * @brief LPTIM345SEL clock source. - */ -#if !defined(STM32_LPTIM345SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM345SEL STM32_LPTIM345SEL_PCLK4 -#endif - -/** - * @brief LPTIM2SEL clock source. - */ -#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK4 -#endif - -/** - * @brief I2C4SEL clock source. - */ -#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) -#define STM32_I2C4SEL STM32_I2C4SEL_PCLK4 -#endif - -/** - * @brief LPUART1SEL clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK4 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32H7xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H7xx_MCUCONF not defined" -#endif - -#if defined(STM32H750xx)&& !defined(STM32H750_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H750_MCUCONF not defined" -#endif - -#if defined(STM32H742xx)&& !defined(STM32H742_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H742_MCUCONF not defined" -#endif - -#if defined(STM32H743xx)&& !defined(STM32H743_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H743_MCUCONF not defined" -#endif - -#if defined(STM32H753xx)&& !defined(STM32H753_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H753_MCUCONF not defined" -#endif - -#if defined(STM32H745xx)&& !defined(STM32H745_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H745_MCUCONF not defined" -#endif - -#if defined(STM32H755xx)&& !defined(STM32H755_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H755_MCUCONF not defined" -#endif - -#if defined(STM32H747xx)&& !defined(STM32H747_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H747_MCUCONF not defined" -#endif - -#if defined(STM32H757xx)&& !defined(STM32H757_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32H757_MCUCONF not defined" -#endif - -/* - * Board file checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/** - * @name Constants depending on VOS and ODEN setting - * @{ - */ -#if STM32_VOS == STM32_VOS_SCALE1 -#define STM32_0WS_THRESHOLD 70000000U -#define STM32_1WS_THRESHOLD 140000000U -#define STM32_2WS_THRESHOLD 210000000U -#define STM32_3WS_THRESHOLD 225000000U -#define STM32_4WS_THRESHOLD 240000000U -#define STM32_PLLOUT_MAX 480000000U -#define STM32_PLLOUT_MIN 1500000U - -#elif STM32_VOS == STM32_VOS_SCALE2 -#define STM32_0WS_THRESHOLD 55000000U -#define STM32_1WS_THRESHOLD 110000000U -#define STM32_2WS_THRESHOLD 165000000U -#define STM32_3WS_THRESHOLD 225000000U -#define STM32_4WS_THRESHOLD 0U -#define STM32_PLLOUT_MAX 300000000U -#define STM32_PLLOUT_MIN 1500000U - -#elif STM32_VOS == STM32_VOS_SCALE3 -#define STM32_0WS_THRESHOLD 45000000U -#define STM32_1WS_THRESHOLD 90000000U -#define STM32_2WS_THRESHOLD 135000000U -#define STM32_3WS_THRESHOLD 180000000U -#define STM32_4WS_THRESHOLD 225000000U -#define STM32_PLLOUT_MAX 200000000U -#define STM32_PLLOUT_MIN 1500000U - -#else -#error "invalid STM32_VOS setting specified" -#endif -/** @} */ - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#define STM32_HSICLK STM32_HSI_OSC - -#else /* !STM32_HSI_ENABLED */ -#define STM32_HSICLK 0U - -#if STM32_SW == STM32_SW_HSI_CK -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_PLLSRC == STM32_PLLSRC_HSI_CK) && \ - (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED) -#error "HSI not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED" -#endif - -#if STM32_CKPERSEL == STM32_CKPERSEL_HSI_CK -#error "HSI not enabled, required by STM32_CKPERSEL" -#endif - -#if STM32_MCO1SEL == STM32_MCO1SEL_HSI_CK -#error "HSI not enabled, required by STM32_MCO1SEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSI48 related checks. - */ -#if STM32_HSI48_ENABLED -#define STM32_HSI48_CK STM32_HSI48_OSC - -#else /* !STM32_HSI48_ENABLED */ -#define STM32_HSI48_CK 0U - -#if STM32_MCO1SEL == STM32_MCO1SEL_HSI48_CK -#error "HSI48 not enabled, required by STM32_MCO1SEL" -#endif - -#endif /* !STM32_HSI48_ENABLED */ - -/* - * CSI related checks. - */ -#if STM32_CSI_ENABLED -#define STM32_CSI_CK STM32_CSI_OSC - -#else /* !STM32_CSI_ENABLED */ -#define STM32_CSI_CK 0U - -#if STM32_SW == STM32_SW_CSI_CK -#error "CSI not enabled, required by STM32_SW" -#endif - -#if (STM32_PLLSRC == STM32_PLLSRC_CSI_CK) && \ - (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED) -#error "CSI not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED" -#endif - -#if STM32_CKPERSEL == STM32_CKPERSEL_CSI_CK -#error "CSI not enabled, required by STM32_CKPERSEL" -#endif - -#if STM32_MCO2SEL == STM32_MCO2SEL_CSI_CK -#error "CSI not enabled, required by STM32_MCO2SEL" -#endif - -#endif /* !STM32_CSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if !defined(STM32_HSECLK) -#error "HSE frequency not defined" -#endif - -#define STM32_HSE_CK STM32_HSECLK - -#if STM32_HSECLK == 0 -#error "HSE oscllator not available" -#else /* STM32_HSECLK != 0 */ -#if defined(STM32_HSE_BYPASS) -#if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN..STM32_HSECLK_BYP_MAX)" -#endif -#else /* !defined(STM32_HSE_BYPASS) */ -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN..STM32_HSECLK_MAX)" -#endif -#endif /* !defined(STM32_HSE_BYPASS) */ -#endif /* STM32_HSECLK != 0 */ -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE_CK -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_PLLSRC == STM32_PLLSRC_HSE_CK) && \ - (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED) -#error "HSE not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED" -#endif - -#if STM32_MCO1SEL == STM32_MCO1SEL_HSE_CK -#error "HSE not enabled, required by STM32_MCO1SEL" -#endif - -#if STM32_MCO2SEL == STM32_MCO2SEL_HSE_CK -#error "HSE not enabled, required by STM32_MCO2SEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSE_1M_CK -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#define STM32_LSI_CK STM32_LSI_OSC - -#else /* !STM32_LSI_ENABLED */ -#define STM32_LSI_CK 0U - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI_CK) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#if STM32_MCO2SEL == STM32_MCO2SEL_LSI_CK -#error "HSE not enabled, required by STM32_MCO2SEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if !defined(STM32_LSECLK) -#error "LSE frequency not defined" -#endif - -#define STM32_LSE_CK STM32_LSECLK - -#if (STM32_LSE_CK == 0) -#error "LSE oscillator not available" -#endif - -#if defined(STM32_LSE_BYPASS) -#if (STM32_LSE_CK < STM32_LSE_CK_MIN) || (STM32_LSE_CK > STM32_LSE_CK_BYP_MAX) -#error "STM32_LSE_CK outside acceptable range (STM32_LSE_CK_MIN..STM32_LSE_CK_BYP_MAX)" -#endif -#else -#if (STM32_LSE_CK < STM32_LSE_CK_MIN) || (STM32_LSE_CK > STM32_LSE_CK_MAX) -#error "STM32_LSE_CK outside acceptable range (STM32_LSE_CK_MIN..STM32_LSE_CK_MAX)" -#endif -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)..(3<<3))" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE_CK -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#if STM32_MCO1SEL == STM32_MCO1SEL_LSE_CK -#error "LSE not enabled, required by STM32_MCO1SEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief HSI divided clock. - */ -#if (STM32_HSIDIV == STM32_HSIDIV_DIV1) || defined(__DOXYGEN__) -#define STM32_HSI_CK (STM32_HSICLK / 1U) -#elif STM32_HSIDIV == STM32_HSIDIV_DIV2 -#define STM32_HSI_CK (STM32_HSICLK / 2U) -#elif STM32_HSIDIV == STM32_HSIDIV_DIV4 -#define STM32_HSI_CK (STM32_HSICLK / 4U) -#elif STM32_HSIDIV == STM32_HSIDIV_DIV8 -#define STM32_HSI_CK (STM32_HSICLK / 8U) -#else -#error "invalid STM32_HSIDIV value specified" -#endif - -/** - * @brief HSE divided clock for RTC. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_HSE_1M_CK (STM32_HSE_CK / STM32_RTCPRE_VALUE) -#else -#error "invalid STM32_RTCPRE_VALUE value specified" -#endif - -/** - * @brief PLLs input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE_CK) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN STM32_HSE_CK - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI_CK -#define STM32_PLLCLKIN STM32_HSI_CK - -#elif STM32_PLLSRC == STM32_PLLSRC_CSI_CK -#define STM32_PLLCLKIN STM32_CSI_CK - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/** - * @brief PLL1 DIVM field. - */ -#if ((STM32_PLL1_DIVM_VALUE >= 1) && (STM32_PLL1_DIVM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLL1_DIVM (STM32_PLL1_DIVM_VALUE << 4) -#define STM32_PLL1_REF_CK (STM32_PLLCLKIN / STM32_PLL1_DIVM_VALUE) -#else -#error "invalid STM32_PLL1_DIVM_VALUE value specified" -#endif - -/* - * PLL1 input frequency range check. - */ -#if (STM32_PLL1_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL1_REF_CK > STM32_PLLIN_MAX) -#error "STM32_PLL1_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)" -#endif - -/** - * @brief PLL1 input range selector. - */ -#if (STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_0 -#elif STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD2 -#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_1 -#elif STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD3 -#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_2 -#else -#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_3 -#endif - -/** - * @brief PLL2 DIVM field. - */ -#if ((STM32_PLL2_DIVM_VALUE >= 1) && (STM32_PLL2_DIVM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2_DIVM (STM32_PLL2_DIVM_VALUE << 12) -#define STM32_PLL2_REF_CK (STM32_PLLCLKIN / STM32_PLL2_DIVM_VALUE) -#else -#error "invalid STM32_PLL2_DIVM_VALUE value specified" -#endif - -/* - * PLL2 input frequency range check. - */ -#if (STM32_PLL2_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL2_REF_CK > STM32_PLLIN_MAX) -#error "STM32_PLL2_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)" -#endif - -/** - * @brief PLL2 input range selector. - */ -#if (STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_0 -#elif STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD2 -#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_1 -#elif STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD3 -#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_2 -#else -#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_3 -#endif - -/** - * @brief PLL3 DIVM field. - */ -#if ((STM32_PLL3_DIVM_VALUE >= 1) && (STM32_PLL3_DIVM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3_DIVM (STM32_PLL3_DIVM_VALUE << 20) -#define STM32_PLL3_REF_CK (STM32_PLLCLKIN / STM32_PLL3_DIVM_VALUE) -#else -#error "invalid STM32_PLL3_DIVM_VALUE value specified" -#endif - -/* - * PLL3 input frequency range check. - */ -#if (STM32_PLL3_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL3_REF_CK > STM32_PLLIN_MAX) -#error "STM32_PLL3_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)" -#endif - -/** - * @brief PLL3 input range selector. - */ -#if (STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_0 -#elif STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD2 -#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_1 -#elif STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD3 -#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_2 -#else -#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_3 -#endif - -/** - * @brief PLL1 DIVN field. - */ -#if ((STM32_PLL1_DIVN_VALUE >= 4) && (STM32_PLL1_DIVN_VALUE <= 512)) || \ - defined(__DOXYGEN__) -#define STM32_PLL1_DIVN ((STM32_PLL1_DIVN_VALUE - 1U) << 0U) -#else -#error "invalid STM32_PLL1_DIVN_VALUE value specified" -#endif - -/** - * @brief PLL2 DIVN field. - */ -#if ((STM32_PLL2_DIVN_VALUE >= 4) && (STM32_PLL2_DIVN_VALUE <= 512)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2_DIVN ((STM32_PLL2_DIVN_VALUE - 1U) << 0U) -#else -#error "invalid STM32_PLL2_DIVN_VALUE value specified" -#endif - -/** - * @brief PLL3 DIVN field. - */ -#if ((STM32_PLL3_DIVN_VALUE >= 4) && (STM32_PLL3_DIVN_VALUE <= 512)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3_DIVN ((STM32_PLL3_DIVN_VALUE - 1U) << 0U) -#else -#error "invalid STM32_PLL3_DIVN_VALUE value specified" -#endif - -/** - * @brief PLL1 FRACN field. - */ -#if ((STM32_PLL1_FRACN_VALUE >= 0) && (STM32_PLL1_FRACN_VALUE <= 8191)) || \ - defined(__DOXYGEN__) -#define STM32_PLL1_FRACN (STM32_PLL1_FRACN_VALUE << 3U) -#else -#error "invalid STM32_PLL1_FRACN_VALUE value specified" -#endif - -/** - * @brief PLL2 FRACN field. - */ -#if ((STM32_PLL2_FRACN_VALUE >= 0) && (STM32_PLL2_FRACN_VALUE <= 8191)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2_FRACN (STM32_PLL2_FRACN_VALUE << 3U) -#else -#error "invalid STM32_PLL2_FRACN_VALUE value specified" -#endif - -/** - * @brief PLL3 FRACN field. - */ -#if ((STM32_PLL3_FRACN_VALUE >= 0) && (STM32_PLL3_FRACN_VALUE <= 8191)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3_FRACN (STM32_PLL3_FRACN_VALUE << 3U) -#else -#error "invalid STM32_PLL3_FRACN_VALUE value specified" -#endif - -/** - * @brief PLL1 DIVP field. - */ -#if ((STM32_PLL1_DIVP_VALUE >= 2) && (STM32_PLL1_DIVP_VALUE <= 128) && \ - ((STM32_PLL1_DIVP_VALUE & 1U) == 0U)) || \ - defined(__DOXYGEN__) -#define STM32_PLL1_DIVP ((STM32_PLL1_DIVP_VALUE - 1U) << 9U) -#else -#error "invalid STM32_PLL1_DIVP_VALUE value specified" -#endif - -/** - * @brief PLL2 DIVP field. - */ -#if ((STM32_PLL2_DIVP_VALUE >= 2) && (STM32_PLL2_DIVP_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2_DIVP ((STM32_PLL2_DIVP_VALUE - 1U) << 9U) -#else -#error "invalid STM32_PLL2_DIVP_VALUE value specified" -#endif - -/** - * @brief PLL3 DIVP field. - */ -#if ((STM32_PLL3_DIVP_VALUE >= 2) && (STM32_PLL3_DIVP_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3_DIVP ((STM32_PLL3_DIVP_VALUE - 1U) << 9U) -#else -#error "invalid STM32_PLL3_DIVP_VALUE value specified" -#endif - -/** - * @brief PLL1 DIVQ field. - */ -#if ((STM32_PLL1_DIVQ_VALUE >= 1) && (STM32_PLL1_DIVQ_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL1_DIVQ ((STM32_PLL1_DIVQ_VALUE - 1U) << 16U) -#else -#error "invalid STM32_PLL1_DIVQ_VALUE value specified" -#endif - -/** - * @brief PLL2 DIVQ field. - */ -#if ((STM32_PLL2_DIVQ_VALUE >= 1) && (STM32_PLL2_DIVQ_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2_DIVQ ((STM32_PLL2_DIVQ_VALUE - 1U) << 16U) -#else -#error "invalid STM32_PLL2_DIVQ_VALUE value specified" -#endif - -/** - * @brief PLL3 DIVQ field. - */ -#if ((STM32_PLL3_DIVQ_VALUE >= 1) && (STM32_PLL3_DIVQ_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3_DIVQ ((STM32_PLL3_DIVQ_VALUE - 1U) << 16U) -#else -#error "invalid STM32_PLL3_DIVQ_VALUE value specified" -#endif - -/** - * @brief PLL1 DIVR field. - */ -#if ((STM32_PLL1_DIVR_VALUE >= 1) && (STM32_PLL1_DIVR_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL1_DIVR ((STM32_PLL1_DIVR_VALUE - 1U) << 24U) -#else -#error "invalid STM32_PLL1_DIVR_VALUE value specified" -#endif - -/** - * @brief PLL2 DIVR field. - */ -#if ((STM32_PLL2_DIVR_VALUE >= 1) && (STM32_PLL2_DIVR_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL2_DIVR ((STM32_PLL2_DIVR_VALUE - 1U) << 24U) -#else -#error "invalid STM32_PLL2_DIVR_VALUE value specified" -#endif - -/** - * @brief PLL3 DIVR field. - */ -#if ((STM32_PLL3_DIVR_VALUE >= 1) && (STM32_PLL3_DIVR_VALUE <= 128)) || \ - defined(__DOXYGEN__) -#define STM32_PLL3_DIVR ((STM32_PLL3_DIVR_VALUE - 1U) << 24U) -#else -#error "invalid STM32_PLL3_DIVR_VALUE value specified" -#endif - -/** - * @brief PLL1 VCO frequency. - */ -#define STM32_PLL1_VCO_CK (STM32_PLL1_REF_CK * STM32_PLL1_DIVN_VALUE) - -/* - * PLL1 VCO frequency range check. - */ -#if (STM32_PLL1_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL1_VCO_CK > STM32_PLLVCO_MAX) -#error "STM32_PLL1_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)" -#endif - -/* - * PLL1 VCO mode. - */ -#if (STM32_PLL1_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_PLL1VCOSEL 0U -#else -#define STM32_PLLCFGR_PLL1VCOSEL RCC_PLLCFGR_PLL1VCOSEL -#endif - -/** - * @brief PLL2 VCO frequency. - */ -#define STM32_PLL2_VCO_CK (STM32_PLL2_REF_CK * STM32_PLL2_DIVN_VALUE) - -/* - * PLL2 VCO frequency range check. - */ -#if (STM32_PLL2_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL2_VCO_CK > STM32_PLLVCO_MAX) -#error "STM32_PLL2_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)" -#endif - -/* - * PLL2 VCO mode. - */ -#if (STM32_PLL2_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_PLL2VCOSEL 0U -#else -#define STM32_PLLCFGR_PLL2VCOSEL RCC_PLLCFGR_PLL2VCOSEL -#endif - -/** - * @brief PLL3 VCO frequency. - */ -#define STM32_PLL3_VCO_CK (STM32_PLL3_REF_CK * STM32_PLL3_DIVN_VALUE) - -/* - * PLL3 VCO frequency range check. - */ -#if (STM32_PLL3_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL3_VCO_CK > STM32_PLLVCO_MAX) -#error "STM32_PLL3_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)" -#endif - -/* - * PLL3 VCO mode. - */ -#if (STM32_PLL3_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_PLLCFGR_PLL3VCOSEL 0U -#else -#define STM32_PLLCFGR_PLL3VCOSEL RCC_PLLCFGR_PLL3VCOSEL -#endif - -#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_P_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL1 P output clock frequency. - */ -#define STM32_PLL1_P_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVP_VALUE) - -/* - * PLL1 P output frequency range check. - */ -#if (STM32_PLL1_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_P_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL1_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL1_P_CK 0U -#endif - -#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_P_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL2 P output clock frequency. - */ -#define STM32_PLL2_P_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVP_VALUE) - -/* - * PLL2 P output frequency range check. - */ -#if (STM32_PLL2_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_P_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL2_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL2_P_CK 0U -#endif - -#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_P_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL3 P output clock frequency. - */ -#define STM32_PLL3_P_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVP_VALUE) - -/* - * PLL3 P output frequency range check. - */ -#if (STM32_PLL3_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_P_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL3_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL3_P_CK 0U -#endif - -#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_Q_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL1 Q output clock frequency. - */ -#define STM32_PLL1_Q_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVQ_VALUE) - -/* - * PLL1 Q output frequency range check. - */ -#if (STM32_PLL1_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_Q_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL1_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL1_Q_CK 0U -#endif - -#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_Q_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL2 Q output clock frequency. - */ -#define STM32_PLL2_Q_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVQ_VALUE) - -/* - * PLL2 Q output frequency range check. - */ -#if (STM32_PLL2_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_Q_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL2_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL2_Q_CK 0U -#endif - -#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_Q_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL3 Q output clock frequency. - */ -#define STM32_PLL3_Q_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVQ_VALUE) - -/* - * PLL3 Q output frequency range check. - */ -#if (STM32_PLL3_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_Q_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL3_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL3_Q_CK 0U -#endif - -#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_R_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL1 R output clock frequency. - */ -#define STM32_PLL1_R_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVR_VALUE) - -/* - * PLL1 R output frequency range check. - */ -#if (STM32_PLL1_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_R_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL1_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL1_R_CK 0U -#endif - -#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_R_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL2 R output clock frequency. - */ -#define STM32_PLL2_R_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVR_VALUE) - -/* - * PLL2 R output frequency range check. - */ -#if (STM32_PLL2_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_R_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL2_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL2_R_CK 0U -#endif - -#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_R_ENABLED == TRUE)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL3 R output clock frequency. - */ -#define STM32_PLL3_R_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVR_VALUE) - -/* - * PLL3 R output frequency range check. - */ -#if (STM32_PLL3_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_R_CK > STM32_PLLOUT_MAX) -#error "STM32_PLL3_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" -#endif -#else -#define STM32_PLL3_R_CK 0U -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_HSI_CK) || defined(__DOXYGEN__) -#define STM32_SYS_CK STM32_HSI_CK - -#elif (STM32_SW == STM32_SW_CSI_CK) -#define STM32_SYS_CK STM32_CSI_CK - -#elif (STM32_SW == STM32_SW_HSE_CK) -#define STM32_SYS_CK STM32_HSE_CK - -#elif (STM32_SW == STM32_SW_PLL1_P_CK) -#define STM32_SYS_CK STM32_PLL1_P_CK - -#else -#error "invalid STM32_SW value specified" -#endif - -/* - * Check on the system clock. - */ -#if STM32_SYS_CK > STM32_SYSCLK_MAX -#error "STM32_SYS_CK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/* - * ODEN setting based on clock frequency. - */ -#if STM32_SYS_CK > STM32_SYSCLK_MAX_NOBOOST -#define STM32_ODEN STM32_ODEN_ENABLED -#else -#define STM32_ODEN STM32_ODEN_DISABLED -#endif - -/** - * @brief Peripherals clock source. - */ -#if (STM32_CKPERSEL == STM32_CKPERSEL_HSI_CK) || defined(__DOXYGEN__) -#define STM32_PER_CK STM32_HSI_CK - -#elif (STM32_CKPERSEL == STM32_CKPERSEL_CSI_CK) -#define STM32_PER_CK STM32_CSI_CK - -#elif (STM32_CKPERSEL == STM32_CKPERSEL_HSE_CK) -#define STM32_PER_CK STM32_HSE_CK - -#else -#error "invalid STM32_CKPERSEL value specified" -#endif - -/* - * Check on the peripherals clock. - */ -#if STM32_PER_CK > STM32_HCLK_MAX -#error "STM32_PER_CK above maximum rated frequency (STM32_HCLK_MAX)" -#endif - -/** - * @brief MCO1 divider clock. - */ -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI_CK) || defined(__DOXYGEN__) -#define STM32_MCO1DIVCLK STM32_HSI_CK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE_CK -#define STM32_MCO1DIVCLK STM32_LSE_CK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE_CK -#define STM32_MCO1DIVCLK STM32_HSE_CK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL1_Q_CK -#define STM32_MCO1DIVCLK STM32_PLL1_P_CK - -#elif STM32_MCO1SEL == STM32_MCO1SEL_HSI48_CK -#define STM32_MCO1DIVCLK STM32_HSI48_CK - -#else -#error "invalid STM32_MCO1SEL value specified" -#endif - -/** - * @brief MCO1 output pin clock. - */ -#if (STM32_MCO1PRE_VALUE < 1) || (STM32_MCO1PRE_VALUE > 15) -#error "STM32_MCO1PRE_VALUE outside acceptable range (1..15)" -#endif - -/** - * @brief MCO2 divider clock. - */ -#if (STM32_MCO2SEL == STM32_MCO2SEL_SYS_CK) || defined(__DOXYGEN__) -#define STM32_MCO2DIVCLK STM32_SYS_CK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL1_P_CK -#define STM32_MCO2DIVCLK STM32_PLL2_P_CK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_HSE_CK -#define STM32_MCO2DIVCLK STM32_HSE_CK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL2_P_CK -#define STM32_MCO2DIVCLK STM32_PLL2_P_CK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_CSI_CK -#define STM32_MCO2DIVCLK STM32_CSI_CK - -#elif STM32_MCO2SEL == STM32_MCO2SEL_LSI_CK -#define STM32_MCO2DIVCLK STM32_LSI_CK - -#else -#error "invalid STM32_MCO2SEL value specified" -#endif - -/** - * @brief MCO2 output pin clock. - */ -#if (STM32_MCO2PRE_VALUE < 1) || (STM32_MCO2PRE_VALUE > 15) -#error "STM32_MCO2PRE_VALUE outside acceptable range (1..15)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLK) || defined(__DOXYGEN__) -#define STM32_RTC_CK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE_CK -#define STM32_RTC_CK STM32_LSE_CK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI_CK -#define STM32_RTC_CK STM32_LSI_CK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSE_1M_CK -#define STM32_RTC_CK STM32_HSE_1M_CK - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/* - * Check on the RTC clock. - */ -#if STM32_RTC_CK > 1000000 -#error "STM32_RTC_CK above maximum rated frequency (1000000)" -#endif - -/** - * @brief D1CPRE clock. - */ -#if (STM32_D1CPRE == STM32_D1CPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 1U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV2 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 2U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV4 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 4U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV8 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 8U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV16 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 16U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV64 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 64U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV128 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 128U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV256 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 256U) -#elif STM32_D1CPRE == STM32_D1CPRE_DIV512 -#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 512U) -#else -#error "invalid STM32_D1CPRE value specified" -#endif - -/** - * @brief HCLK clock. - */ -#if (STM32_D1HPRE == STM32_D1HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 1U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV2 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 2U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV4 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 4U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV8 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 8U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV16 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 16U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV64 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 64U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV128 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 128U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV256 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 256U) -#elif STM32_D1HPRE == STM32_D1HPRE_DIV512 -#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 512U) -#else -#error "invalid STM32_D1HPRE value specified" -#endif - -/** - * @brief Core clock. - */ -#define STM32_CORE1_CK STM32_SYS_D1CPRE_CK - -/** - * @brief Core clock. - */ -#define STM32_CORE2_CK STM32_HCLK - -#if (STM32_TARGET_CORE == 1) || defined(__DOXYGEN__) - -#if STM32_HAS_M7 != TRUE -#error "Cortex-M7 not present in this device" -#endif -#define STM32_CORE_CK STM32_CORE1_CK - -#elif STM32_TARGET_CORE == 2 - -#if STM32_HAS_M4 != TRUE -#error "Cortex-M4 not present in this device" -#endif -#define STM32_CORE_CK STM32_CORE2_CK - -#else -#error "invalid STM32_TARGET_CORE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_HCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_HCLK_MAX)" -#endif - -/** - * @brief D1 PCLK3 clock. - */ -#if (STM32_D1PPRE3 == STM32_D1PPRE3_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK3 (STM32_HCLK / 1U) -#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV2 -#define STM32_PCLK3 (STM32_HCLK / 2U) -#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV4 -#define STM32_PCLK3 (STM32_HCLK / 4U) -#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV8 -#define STM32_PCLK3 (STM32_HCLK / 8U) -#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV16 -#define STM32_PCLK3 (STM32_HCLK / 16U) -#else -#error "invalid STM32_D1PPRE3 value specified" -#endif - -/* - * D1 PCLK3 frequency check. - */ -#if STM32_PCLK3 > STM32_PCLK3_MAX -#error "STM32_PCLK3 exceeding maximum frequency (STM32_PCLK3_MAX)" -#endif - -/** - * @brief D2 PCLK1 clock. - */ -#if (STM32_D2PPRE1 == STM32_D2PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1U) -#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2U) -#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4U) -#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8U) -#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16U) -#else -#error "invalid STM32_D2PPRE1 value specified" -#endif - -/* - * D2 PCLK1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief D2 PCLK2 clock. - */ -#if (STM32_D2PPRE2 == STM32_D2PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1U) -#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2U) -#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4U) -#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8U) -#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16U) -#else -#error "invalid STM32_D2PPRE2 value specified" -#endif - -/* - * D2 PCLK2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief D3 PCLK4 clock. - */ -#if (STM32_D3PPRE4 == STM32_D3PPRE4_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK4 (STM32_HCLK / 1U) -#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV2 -#define STM32_PCLK4 (STM32_HCLK / 2U) -#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV4 -#define STM32_PCLK4 (STM32_HCLK / 4U) -#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV8 -#define STM32_PCLK4 (STM32_HCLK / 8U) -#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV16 -#define STM32_PCLK4 (STM32_HCLK / 16U) -#else -#error "invalid STM32_D3PPRE4 value specified" -#endif - -/* - * D3 PCLK4 frequency check. - */ -#if STM32_PCLK4 > STM32_PCLK4_MAX -#error "STM32_PCLK4 exceeding maximum frequency (STM32_PCLK4_MAX)" -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000000 - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS 0x00000001 - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS 0x00000002 - -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS 0x00000003 - -#elif STM32_HCLK <= STM32_4WS_THRESHOLD -#define STM32_FLASHBITS 0x00000004 - -#else -#define STM32_FLASHBITS 0x00000007 -#endif - -#if (STM32_D2PPRE1 == STM32_D2PPRE1_DIV1) || defined(__DOXYGEN__) -/** - * @brief Clock of timers connected to APB1 - */ -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#if (STM32_TIMPRE_ENABLE == FALSE) || (STM32_D2PPRE1 == STM32_D2PPRE1_DIV2) -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 4) -#endif -#endif - -#if (STM32_D2PPRE2 == STM32_D2PPRE2_DIV1) || defined(__DOXYGEN__) -/** - * @brief Clock of timers connected to APB2. - */ -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#if (STM32_TIMPRE_ENABLE == FALSE) || (STM32_D2PPRE2 == STM32_D2PPRE2_DIV2) -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 4) -#endif -#endif - -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) -/** - * @brief LPTIM1 clock. - */ -#define STM32_LPTIM1CLK STM32_PCLK1 - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PLL2_P_CK -#define STM32_LPTIM1CLK STM32_PLL2_P_CK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PLL3_R_CK -#define STM32_LPTIM1CLK STM32_PLL3_R_CK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE_CK -#define STM32_LPTIM1CLK STM32_LSE_CK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI_CK -#define STM32_LPTIM1CLK STM32_LSI_CK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PER_CK -#define STM32_LPTIM1CLK STM32_PER_CK -#else -#error "invalid source selected for STM32_LPTIM1SEL clock" -#endif - -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK4) || defined(__DOXYGEN__) -/** - * @brief LPTIM2 clock. - */ -#define STM32_LPTIM2CLK STM32_PCLK4 - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PLL2_P_CK -#define STM32_LPTIM2CLK STM32_PLL2_P_CK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PLL3_P_CK -#define STM32_LPTIM2CLK STM32_PLL3_P_CK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE_CK -#define STM32_LPTIM2CLK STM32_LSE_CK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI_CK -#define STM32_LPTIM2CLK STM32_LSI_CK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PER_CK -#define STM32_LPTIM2CLK STM32_PER_CK -#else -#error "invalid source selected for STM32_LPTIM2SEL clock" -#endif - -#if (STM32_LPTIM345SEL == STM32_LPTIM345SEL_PCLK4) || defined(__DOXYGEN__) -/** - * @brief LPTIM3 clock. - */ -#define STM32_LPTIM3CLK STM32_PCLK4 - -/** - * @brief LPTIM4 clock. - */ -#define STM32_LPTIM4CLK STM32_PCLK4 - -/** - * @brief LPTIM5 clock. - */ -#define STM32_LPTIM5CLK STM32_PCLK4 - -#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PLL2_P_CK -#define STM32_LPTIM3CLK STM32_PLL2_P_CK -#define STM32_LPTIM4CLK STM32_PLL2_P_CK -#define STM32_LPTIM5CLK STM32_PLL2_P_CK -#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PLL3_P_CK -#define STM32_LPTIM3CLK STM32_PLL3_P_CK -#define STM32_LPTIM4CLK STM32_PLL3_P_CK -#define STM32_LPTIM5CLK STM32_PLL3_P_CK -#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_LSE_CK -#define STM32_LPTIM3CLK STM32_LSE_CK -#define STM32_LPTIM4CLK STM32_LSE_CK -#define STM32_LPTIM5CLK STM32_LSE_CK -#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_LSI_CK -#define STM32_LPTIM3CLK STM32_LSI_CK -#define STM32_LPTIM4CLK STM32_LSI_CK -#define STM32_LPTIM5CLK STM32_LSI_CK -#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PER_CK -#define STM32_LPTIM3CLK STM32_PER_CK -#define STM32_LPTIM4CLK STM32_PER_CK -#define STM32_LPTIM5CLK STM32_PER_CK -#else -#error "invalid source selected for STM32_LPTIM345SEL clock" -#endif - -#if (STM32_USART16SEL == STM32_USART16SEL_PCLK2) || defined(__DOXYGEN__) -/** - * @brief USART1 clock. - */ -#define STM32_USART1CLK STM32_PCLK2 - -/** - * @brief USART6 clock. - */ -#define STM32_USART6CLK STM32_PCLK2 - -#elif STM32_USART16SEL == STM32_USART16SEL_PLL2_Q_CK -#define STM32_USART1CLK STM32_PLL2_Q_CK -#define STM32_USART6CLK STM32_PLL2_Q_CK -#elif STM32_USART16SEL == STM32_USART16SEL_PLL3_Q_CK -#define STM32_USART1CLK STM32_PLL3_Q_CK -#define STM32_USART6CLK STM32_PLL3_Q_CK -#elif STM32_USART16SEL == STM32_USART16SEL_HSI_KER_CK -#define STM32_USART1CLK STM32_HSI_CK -#define STM32_USART6CLK STM32_HSI_CK -#elif STM32_USART16SEL == STM32_USART16SEL_CSI_KER_CK -#define STM32_USART1CLK STM32_CSI_CK -#define STM32_USART6CLK STM32_CSI_CK -#elif STM32_USART16SEL == STM32_USART16SEL_LSE_CK -#define STM32_USART1CLK STM32_LSE_CK -#define STM32_USART6CLK STM32_LSE_CK -#else -#error "invalid source selected for STM32_USART16SEL clock" -#endif - -#if (STM32_USART234578SEL == STM32_USART234578SEL_PCLK1) || defined(__DOXYGEN__) -/** - * @brief USART2 clock. - */ -#define STM32_USART2CLK STM32_PCLK1 - -/** - * @brief USART3 clock. - */ -#define STM32_USART3CLK STM32_PCLK1 - -/** - * @brief USART4 clock. - */ -#define STM32_UART4CLK STM32_PCLK1 - -/** - * @brief USART5 clock. - */ -#define STM32_UART5CLK STM32_PCLK1 - -/** - * @brief USART7 clock. - */ -#define STM32_UART7CLK STM32_PCLK1 - -/** - * @brief USART8 clock. - */ -#define STM32_UART8CLK STM32_PCLK1 - -#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL2_Q_CK -#define STM32_USART2CLK STM32_PLL2_Q_CK -#define STM32_USART3CLK STM32_PLL2_Q_CK -#define STM32_UART4CLK STM32_PLL2_Q_CK -#define STM32_UART5CLK STM32_PLL2_Q_CK -#define STM32_UART7CLK STM32_PLL2_Q_CK -#define STM32_UART8CLK STM32_PLL2_Q_CK -#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL3_Q_CK -#define STM32_USART2CLK STM32_PLL3_Q_CK -#define STM32_USART3CLK STM32_PLL3_Q_CK -#define STM32_UART4CLK STM32_PLL3_Q_CK -#define STM32_UART5CLK STM32_PLL3_Q_CK -#define STM32_UART7CLK STM32_PLL3_Q_CK -#define STM32_UART8CLK STM32_PLL3_Q_CK -#elif STM32_USART234578SEL == STM32_USART234578SEL_HSI_KER_CK -#define STM32_USART2CLK STM32_HSI_CK -#define STM32_USART3CLK STM32_HSI_CK -#define STM32_UART4CLK STM32_HSI_CK -#define STM32_UART5CLK STM32_HSI_CK -#define STM32_UART7CLK STM32_HSI_CK -#define STM32_UART8CLK STM32_HSI_CK -#elif STM32_USART234578SEL == STM32_USART234578SEL_CSI_KER_CK -#define STM32_USART2CLK STM32_CSI_CK -#define STM32_USART3CLK STM32_CSI_CK -#define STM32_UART4CLK STM32_CSI_CK -#define STM32_UART5CLK STM32_CSI_CK -#define STM32_UART7CLK STM32_CSI_CK -#define STM32_UART8CLK STM32_CSI_CK -#elif STM32_USART234578SEL == STM32_USART234578SEL_LSE_CK -#define STM32_USART2CLK STM32_LSE_CK -#define STM32_USART3CLK STM32_LSE_CK -#define STM32_UART4CLK STM32_LSE_CK -#define STM32_UART6CLK STM32_LSE_CK -#define STM32_UART7CLK STM32_LSE_CK -#define STM32_UART8CLK STM32_LSE_CK -#else -#error "invalid source selected for STM32_USART234578SEL clock" -#endif - -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK4) || defined(__DOXYGEN__) -/** - * @brief LPUART1 clock. - */ -#define STM32_LPUART1CLK STM32_PCLK4 - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_PLL2_Q_CK -#define STM32_LPUART1CLK STM32_PLL2_Q_CK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_PLL3_Q_CK -#define STM32_LPUART1CLK STM32_PLL3_Q_CK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI_KER_CK -#define STM32_LPUART1CLK STM32_HSI_CK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_CSI_KER_CK -#define STM32_LPUART1CLK STM32_CSI_CK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE_CK -#define STM32_LPUART1CLK STM32_LSE_CK -#else -#error "invalid source selected for STM32_LPUART1SEL clock" -#endif - -#if (STM32_SPI123SEL == STM32_SPI123SEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SPI1 clock. - */ -#define STM32_SPI1CLK STM32_PLL1_Q_CK - -/** - * @brief SPI2 clock. - */ -#define STM32_SPI2CLK STM32_PLL1_Q_CK - -/** - * @brief SPI3 clock. - */ -#define STM32_SPI3CLK STM32_PLL1_Q_CK -#elif STM32_SPI123SEL == STM32_SPI123SEL_PLL2_P_CK -#define STM32_SPI1CLK STM32_PLL2_P_CK -#define STM32_SPI2CLK STM32_PLL2_P_CK -#define STM32_SPI3CLK STM32_PLL2_P_CK -#elif STM32_SPI123SEL == STM32_SPI123SEL_PLL3_P_CK -#define STM32_SPI1CLK STM32_PLL3_P_CK -#define STM32_SPI2CLK STM32_PLL3_P_CK -#define STM32_SPI3CLK STM32_PLL3_P_CK -#elif STM32_SPI123SEL == STM32_SPI123SEL_I2S_CKIN -#define STM32_SPI1CLK 0 /* Unknown, would require a board value */ -#define STM32_SPI2CLK 0 /* Unknown, would require a board value */ -#define STM32_SPI3CLK 0 /* Unknown, would require a board value */ -#elif STM32_SPI123SEL == STM32_SPI123SEL_PER_CK -#define STM32_SPI1CLK STM32_PER_CK -#define STM32_SPI2CLK STM32_PER_CK -#define STM32_SPI3CLK STM32_PER_CK -#else -#error "invalid source selected for STM32_SPI123SEL clock" -#endif - -#if (STM32_SPI45SEL == STM32_SPI45SEL_PCLK2) || defined(__DOXYGEN__) -/** - * @brief SPI4 clock. - */ -#define STM32_SPI4CLK STM32_PCLK2 - -/** - * @brief SPI5 clock. - */ -#define STM32_SPI5CLK STM32_PCLK2 - -#elif STM32_SPI45SEL == STM32_SPI45SEL_PLL2_Q_CK -#define STM32_SPI4CLK STM32_PLL2_Q_CK -#define STM32_SPI5CLK STM32_PLL2_Q_CK -#elif STM32_SPI45SEL == STM32_SPI45SEL_PLL3_Q_CK -#define STM32_SPI4CLK STM32_PLL3_Q_CK -#define STM32_SPI5CLK STM32_PLL3_Q_CK -#elif STM32_SPI45SEL == STM32_SPI45SEL_HSI_KER_CK -#define STM32_SPI4CLK STM32_HSI_CK -#define STM32_SPI5CLK STM32_HSI_CK -#elif STM32_SPI45SEL == STM32_SPI45SEL_CSI_KER_CK -#define STM32_SPI4CLK STM32_CSI_CK -#define STM32_SPI5CLK STM32_CSI_CK -#elif STM32_SPI45SEL == STM32_SPI45SEL_HSE_CK -#define STM32_SPI4CLK STM32_HSE_CK -#define STM32_SPI5CLK STM32_HSE_CK -#else -#error "invalid source selected for STM32_SPI45SEL clock" -#endif - -#if (STM32_SPI6SEL == STM32_SPI6SEL_PCLK4) || defined(__DOXYGEN__) -/** - * @brief SPI6 clock. - */ -#define STM32_SPI6CLK STM32_PCLK4 - -#elif STM32_SPI6SEL == STM32_SPI6SEL_PLL2_Q_CK -#define STM32_SPI6CLK STM32_PLL2_Q_CK -#elif STM32_SPI6SEL == STM32_SPI6SEL_PLL3_Q_CK -#define STM32_SPI6CLK STM32_PLL3_Q_CK -#elif STM32_SPI6SEL == STM32_SPI6SEL_HSI_KER_CK -#define STM32_SPI6CLK STM32_HSI_CK -#elif STM32_SPI6SEL == STM32_SPI6SEL_CSI_KER_CK -#define STM32_SPI6CLK STM32_CSI_CK -#elif STM32_SPI6SEL == STM32_SPI6SEL_HSE_CK -#define STM32_SPI6CLK STM32_HSE_CK -#else -#error "invalid source selected for STM32_SPI6SEL clock" -#endif - -#if (STM32_I2C123SEL == STM32_I2C123SEL_PCLK1) || defined(__DOXYGEN__) -/** - * @brief I2C1 clock. - */ -#define STM32_I2C1CLK STM32_PCLK1 - -/** - * @brief I2C2 clock. - */ -#define STM32_I2C2CLK STM32_PCLK1 - -/** - * @brief I2C2 clock. - */ -#define STM32_I2C2CLK STM32_PCLK1 - -#elif STM32_I2C123SEL == STM32_I2C123SEL_PLL3_R_CK -#define STM32_I2C1CLK STM32_PLL3_R_CK -#define STM32_I2C2CLK STM32_PLL3_R_CK -#define STM32_I2C2CLK STM32_PLL3_R_CK - -#elif STM32_I2C123SEL == STM32_I2C123SEL_HSI_KER_CK -#define STM32_I2C1CLK STM32_HSI_CK -#define STM32_I2C2CLK STM32_HSI_CK -#define STM32_I2C2CLK STM32_HSI_CK - -#elif STM32_I2C123SEL == STM32_I2C123SEL_CSI_KER_CK -#define STM32_I2C1CLK STM32_CSI_CK -#define STM32_I2C2CLK STM32_CSI_CK -#define STM32_I2C2CLK STM32_CSI_CK -#else -#error "invalid source selected for STM32_I2C123SEL clock" -#endif - -#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK4) || defined(__DOXYGEN__) -/** - * @brief I2C1 clock. - */ -#define STM32_I2C4CLK STM32_PCLK4 - -#elif STM32_I2C4SEL == STM32_I2C4SEL_PLL3_R_CK -#define STM32_I2C4CLK STM32_PLL3_R_CK -#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI_KER_CK -#define STM32_I2C4CLK STM32_HSI_CK -#elif STM32_I2C4SEL == STM32_I2C4SEL_CSI_KER_CK -#define STM32_I2C4CLK STM32_CSI_CK -#else -#error "invalid source selected for STM32_I2C4SEL clock" -#endif - -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SAI1 clock. - */ -#define STM32_SAI1CLK STM32_PLL1_Q_CK - -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL2_P_CK -#define STM32_SAI1CLK STM32_PLL2_P_CK -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL3_P_CK -#define STM32_SAI1CLK STM32_PLL3_P_CK -#elif STM32_SAI1SEL == STM32_SAI1SEL_I2S_CKIN -#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ -#elif STM32_SAI1SEL == STM32_SAI1SEL_PER_CK -#define STM32_SAI1CLK STM32_PER_CK -#else -#error "invalid source selected for STM32_SAI1SEL clock" -#endif - -#if (STM32_SAI23SEL == STM32_SAI23SEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SAI2 clock. - */ -#define STM32_SAI2CLK STM32_PLL1_Q_CK - -/** - * @brief SAI3 clock. - */ -#define STM32_SAI3CLK STM32_PLL1_Q_CK - -#elif STM32_SAI23SEL == STM32_SAI23SEL_PLL2_P_CK -#define STM32_SAI2CLK STM32_PLL2_P_CK -#define STM32_SAI3CLK STM32_PLL2_P_CK -#elif STM32_SAI23SEL == STM32_SAI23SEL_PLL3_P_CK -#define STM32_SAI2CLK STM32_PLL3_P_CK -#define STM32_SAI3CLK STM32_PLL3_P_CK -#elif STM32_SAI23SEL == STM32_SAI23SEL_I2S_CKIN -#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ -#define STM32_SAI3CLK 0 /* Unknown, would require a board value */ -#elif STM32_SAI23SEL == STM32_SAI23SEL_PER_CK -#define STM32_SAI2CLK STM32_PER_CK -#define STM32_SAI3CLK STM32_PER_CK -#else -#error "invalid source selected for STM32_SAI23SEL clock" -#endif - -#if (STM32_SAI4ASEL == STM32_SAI4ASEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SAI4A clock. - */ -#define STM32_SAI4ACLK STM32_PLL1_Q_CK - -#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PLL2_P_CK -#define STM32_SAI4ACLK STM32_PLL2_P_CK -#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PLL3_P_CK -#define STM32_SAI4ACLK STM32_PLL3_P_CK -#elif STM32_SAI4ASEL == STM32_SAI4ASEL_I2S_CKIN -#define STM32_SAI4ACLK 0 /* Unknown, would require a board value */ -#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PER_CK -#define STM32_SAI4ACLK STM32_PER_CK -#else -#error "invalid source selected for STM32_SAI4ASEL clock" -#endif - -#if (STM32_SAI4BSEL == STM32_SAI4BSEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SAI4B clock. - */ -#define STM32_SAI4BCLK STM32_PLL1_Q_CK - -#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PLL2_P_CK -#define STM32_SAI4BCLK STM32_PLL2_P_CK -#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PLL3_P_CK -#define STM32_SAI4BCLK STM32_PLL3_P_CK -#elif STM32_SAI4BSEL == STM32_SAI4BSEL_I2S_CKIN -#define STM32_SAI4BCLK 0 /* Unknown, would require a board value */ -#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PER_CK -#define STM32_SAI4BCLK STM32_PER_CK -#else -#error "invalid source selected for STM32_SAI4BSEL clock" -#endif - -#if (STM32_USBSEL == STM32_USBSEL_DISABLE) || defined(__DOXYGEN__) -/** - * @brief USB clock. - */ -#define STM32_USBCLK 0 - -#elif STM32_USBSEL == STM32_USBSEL_PLL1_Q_CK -#define STM32_USBCLK STM32_PLL1_Q_CK -#elif STM32_USBSEL == STM32_USBSEL_PLL3_Q_CK -#define STM32_USBCLK STM32_PLL3_Q_CK -#elif STM32_USBSEL == STM32_USBSEL_HSI48_CK -#define STM32_USBCLK STM32_HSI48_CK -#else -#error "invalid source selected for STM32_USBSEL clock" -#endif - -#if (STM32_SDMMCSEL == STM32_SDMMCSEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SDMMC1 frequency. - */ -#define STM32_SDMMC1CLK STM32_PLL1_Q_CK - -/** - * @brief SDMMC2 frequency. - */ -#define STM32_SDMMC2CLK STM32_PLL1_Q_CK - -#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLL2_R_CK -#define STM32_SDMMC1CLK STM32_PLL2_R_CK -#define STM32_SDMMC2CLK STM32_PLL2_R_CK -#else -#error "invalid source selected for STM32_SDMMCxSEL clock" -#endif - -#if (STM32_QSPISEL == STM32_QSPISEL_HCLK) || defined(__DOXYGEN__) -/** - * @brief QSPI frequency. - */ -#define STM32_QSPICLK STM32_HCLK - -#elif STM32_QSPISEL == STM32_QSPISEL_PLL1_Q_CK -#define STM32_QSPICLK STM32_PLL1_Q_CK -#elif STM32_QSPISEL == STM32_QSPISEL_PLL2_R_CK -#define STM32_QSPICLK STM32_PLL2_R_CK -#elif STM32_QSPISEL == STM32_QSPISEL_PER_CK -#define STM32_QSPICLK STM32_PER_CK -#else -#error "invalid source selected for STM32_QSPISEL clock" -#endif - -#if (STM32_FMCSEL == STM32_FMCSEL_HCLK) || defined(__DOXYGEN__) -/** - * @brief FMC frequency. - */ -#define STM32_FMCCLK STM32_HCLK - -#elif STM32_FMCSEL == STM32_FMCSEL_PLL1_Q_CK -#define STM32_FMCCLK STM32_PLL1_Q_CK -#elif STM32_FMCSEL == STM32_FMCSEL_PLL2_R_CK -#define STM32_FMCCLK STM32_PLL2_R_CK -#elif STM32_FMCSEL == STM32_FMCSEL_PER_CK -#define STM32_FMCCLK STM32_PER_CK -#else -#error "invalid source selected for STM32_FMCSEL clock" -#endif - -#if (STM32_SWPSEL == STM32_SWPSEL_PCLK1) || defined(__DOXYGEN__) -/** - * @brief SDMMC frequency. - */ -#define STM32_SWPCLK STM32_PCLK1 - -#elif STM32_SWPSEL == STM32_SWPSEL_HSI_KER_CK -#define STM32_SWPCLK STM32_HSI_CK -#else -#error "invalid source selected for STM32_SWPSEL clock" -#endif - -#if (STM32_FDCANSEL == STM32_FDCANSEL_HSE_CK) || defined(__DOXYGEN__) -/** - * @brief FDCAN frequency. - */ -#define STM32_FDCANCLK STM32_HSE_CK - -#elif STM32_FDCANSEL == STM32_FDCANSEL_PLL1_Q_CK -#define STM32_FDCANCLK STM32_PLL1_Q_CK -#elif STM32_FDCANSEL == STM32_FDCANSEL_PLL2_Q_CK -#define STM32_FDCANCLK STM32_PLL2_Q_CK -#else -#error "invalid source selected for STM32_FDCANSEL clock" -#endif - -#if (STM32_DFSDM1SEL == STM32_DFSDM1SEL_PCLK2) || defined(__DOXYGEN__) -/** - * @brief SDMMC frequency. - */ -#define STM32_DFSDM1CLK STM32_PCLK2 - -#elif STM32_DFSDM1SEL == STM32_DFSDM1SEL_SYS_CK -#define STM32_DFSDM1CLK STM32_SYS_CK -#else -#error "invalid source selected for STM32_DFSDM1SEL clock" -#endif - -#if (STM32_SPDIFSEL == STM32_SPDIFSEL_PLL1_Q_CK) || defined(__DOXYGEN__) -/** - * @brief SPDIF frequency. - */ -#define STM32_SPDIFCLK STM32_PLL1_Q_CK - -#elif STM32_SPDIFSEL == STM32_SPDIFSEL_PLL2_R_CK -#define STM32_SPDIFCLK STM32_PLL2_R_CK -#elif STM32_SPDIFSEL == STM32_SPDIFSEL_PLL3_R_CK -#define STM32_SPDIFCLK STM32_PLL3_R_CK -#elif STM32_SPDIFSEL == STM32_SPDIFSEL_HSI_KET_CLK -#define STM32_SPDIFCLK STM32_HSI_CK -#else -#error "invalid source selected for STM32_SPDIFSEL clock" -#endif - -#if (STM32_CECSEL == STM32_CECSEL_LSE_CK) || defined(__DOXYGEN__) -/** - * @brief CEC frequency. - */ -#define STM32_CECCLK STM32_LSE_CK - -#elif STM32_CECSEL == STM32_CECSEL_LSI_CK -#define STM32_CECCLK STM32_LSI_CK -#elif STM32_CECSEL == STM32_CECSEL_CSI_KER_CK -#define STM32_CECCLK STM32_CSI_CK -#elif STM32_CECSEL == STM32_CECSEL_DISABLE -#define STM32_CECCLK 0 -#else -#error "invalid source selected for STM32_CECSEL clock" -#endif - -#if (STM32_RNGSEL == STM32_RNGSEL_HSI48_CK) || defined(__DOXYGEN__) -/** - * @brief RNG frequency. - */ -#define STM32_RNGCLK STM32_HSI48_CK - -#elif STM32_RNGSEL == STM32_RNGSEL_PLL1_Q_CK -#define STM32_RNGCLK STM32_PLL1_Q_CK -#elif STM32_RNGSEL == STM32_RNGSEL_LSE_CK -#define STM32_RNGCLK STM32_LSE_CK -#elif STM32_RNGSEL == STM32_RNGSEL_LSI_CK -#define STM32_RNGCLK STM32_LSI_CK -#else -#error "invalid source selected for STM32_RNGSEL clock" -#endif - -#if (STM32_ADCSEL == STM32_ADCSEL_PLL2_P_CK) || defined(__DOXYGEN__) -/** - * @brief ADC frequency. - */ -#define STM32_ADCCLK STM32_PLL2_P_CK - -#elif STM32_ADCSEL == STM32_ADCSEL_PLL3_R_CK -#define STM32_ADCCLK STM32_PLL3_R_CK -#elif STM32_ADCSEL == STM32_ADCSEL_PER_CK -#define STM32_ADCCLK STM32_PER_CK -#elif STM32_ADCSEL == STM32_ADCSEL_DISABLE -#define STM32_ADCCLK 0 -#else -#error "invalid source selected for STM32_ADCSEL clock" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_mdma.h" -#include "stm32_dma.h" -#include "stm32_bdma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32H7xx/hal_lld.h + * @brief STM32H7xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * - STM32_VDD (as hundredths of Volt). + * . + * One of the following macros must also be defined: + * - STM32H743xx, STM32H753xx very high-performance MCUs. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32H742xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32H742 Single Core Very High Performance with DSP and FPU" + +#elif defined(STM32H743xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32H743 Single Core Very High Performance with DSP and FPU" + +#elif defined(STM32H753xx) +#define PLATFORM_NAME "STM32H753 Single Core Very High Performance with DSP and FPU" + +#elif defined(STM32H745xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32H745 Dual Core Very High Performance with DSP and FPU" + +#elif defined(STM32H755xx) +#define PLATFORM_NAME "STM32H755 Dual Core Very High Performance with DSP and FPU" + +#elif defined(STM32H747xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32H747 Dual Core Very High Performance with DSP and FPU" + +#elif defined(STM32H757xx) +#define PLATFORM_NAME "STM32H757 Dual Core Very High Performance with DSP and FPU" + +#elif defined(STM32H750xx) +#define PLATFORM_NAME "STM32H750 Value Line Very High Performance with DSP and FPU" + +#else +#error "STM32H7xx device not specified" +#endif +/** @} */ + +/** + * @name Sub-family identifier + */ +#if !defined(STM32H7XX) || defined(__DOXYGEN__) +#define STM32H7XX +#endif +/** @} */ + +#if !defined(STM32_ENFORCE_H7_REV_XY) +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Absolute maximum system clock. + */ +#define STM32_SYSCLK_MAX 480000000 + +/** + * @brief Maximum SYSCLK clock frequency without voltage boost. + */ +#define STM32_SYSCLK_MAX_NOBOOST 400000000 + +/** + * @brief Absolute maximum HCLK clock. + */ +#define STM32_HCLK_MAX (STM32_SYSCLK_MAX / 2) + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 50000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_BYP_MIN 4000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSE_CK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSE_CK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSE_CK_MIN 32768 + +/** + * @brief Minimum PLLs input clock frequency.. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief PLLs input threshold frequency 1. + */ +#define STM32_PLLIN_THRESHOLD1 2000000 + +/** + * @brief PLLs input threshold frequency 2. + */ +#define STM32_PLLIN_THRESHOLD2 4000000 + +/** + * @brief PLLs input threshold frequency 3. + */ +#define STM32_PLLIN_THRESHOLD3 8000000 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 16000000 + +/** + * @brief Minimum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MIN 150000000 /* DS says 192, RM says 150. */ + +/** + * @brief Threshold PLLs clock frequency. + */ +#define STM32_PLLVCO_THRESHOLD 420000000 + +/** + * @brief Maximum PLLs VCOH clock frequency. + */ +#define STM32_PLLVCO_MAX 960000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX (STM32_HCLK_MAX / 2) + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX (STM32_HCLK_MAX / 2) + +/** + * @brief Maximum APB3 clock frequency. + */ +#define STM32_PCLK3_MAX (STM32_HCLK_MAX / 2) + +/** + * @brief Maximum APB4 clock frequency. + */ +#define STM32_PCLK4_MAX (STM32_HCLK_MAX / 2) + +/** + * @brief Maximum SPI1, SPI2 and SPI3 clock frequency. + */ +#define STM32_SPI123_MAX 200000000 + +/** + * @brief Maximum SPI4, SPI5 and SPI6 clock frequency. + */ +#define STM32_SPI456_MAX 125000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 50000000 +/** @} */ + +#else /* defined(STM32_ENFORCE_H7_REV_XY) */ + +#define STM32_SYSCLK_MAX 400000000 +#define STM32_SYSCLK_MAX_NOBOOST 400000000 +#define STM32_HCLK_MAX (STM32_SYSCLK_MAX / 2) +#define STM32_HSECLK_MAX 48000000 +#define STM32_HSECLK_BYP_MAX 50000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 4000000 +#define STM32_LSE_CK_MAX 32768 +#define STM32_LSE_CK_BYP_MAX 1000000 +#define STM32_LSE_CK_MIN 32768 +#define STM32_PLLIN_MIN 1000000 +#define STM32_PLLIN_THRESHOLD1 2000000 +#define STM32_PLLIN_THRESHOLD2 4000000 +#define STM32_PLLIN_THRESHOLD3 8000000 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLVCO_MIN 150000000 +#define STM32_PLLVCO_THRESHOLD 420000000 +#define STM32_PLLVCO_MAX 836000000 +#define STM32_PCLK1_MAX (STM32_HCLK_MAX / 2) +#define STM32_PCLK2_MAX (STM32_HCLK_MAX / 2) +#define STM32_PCLK3_MAX (STM32_HCLK_MAX / 2) +#define STM32_PCLK4_MAX (STM32_HCLK_MAX / 2) +#define STM32_SPI123_MAX 133000000 +#define STM32_SPI456_MAX 100000000 +#define STM32_ADCCLK_MAX 36000000 + +#endif /* defined(STM32_ENFORCE_H7_REV_XY) */ + +/** + * @name Internal clock sources frequencies + * @{ + */ +#define STM32_HSI_OSC 64000000 +#define STM32_HSI48_OSC 48000000 +#define STM32_CSI_OSC 4000000 +#define STM32_LSI_OSC 32000 +/** @} */ + +/** + * @name Register helpers not found in ST headers + * @{ + */ +#define RCC_CR_HSIDIV_VALUE(n) ((n) << 3U) + +#define RCC_CFGR_SW_VALUE(n) ((n) << 0U) +#define RCC_CFGR_RTCPRE_VALUE(n) ((n) << 8U) +#define RCC_CFGR_MCO1PRE_VALUE(n) ((n) << 18U) +#define RCC_CFGR_MCO1_VALUE(n) ((n) << 22U) +#define RCC_CFGR_MCO2PRE_VALUE(n) ((n) << 25U) +#define RCC_CFGR_MCO2_VALUE(n) ((n) << 29U) + +#define RCC_D1CFGR_D1HPRE_VALUE(n) ((n) << RCC_D1CFGR_HPRE_Pos) +#define RCC_D1CFGR_D1CPRE_VALUE(n) ((n) << RCC_D1CFGR_D1CPRE_Pos) +#define RCC_D1CFGR_D1PPRE3_VALUE(n) ((n) << RCC_D1CFGR_D1PPRE_Pos) + +#define RCC_D2CFGR_D2PPRE1_VALUE(n) ((n) << RCC_D2CFGR_D2PPRE1_Pos) +#define RCC_D2CFGR_D2PPRE2_VALUE(n) ((n) << RCC_D2CFGR_D2PPRE2_Pos) + +#define RCC_D3CFGR_D3PPRE4_VALUE(n) ((n) << RCC_D3CFGR_D3PPRE_Pos) + +#define RCC_PLLCKSELR_PLLSRC_VALUE(n) ((n) << RCC_PLLCKSELR_PLLSRC_Pos) + +#define RCC_PLLCKSELR_DIVM1_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM1_Pos) +#define RCC_PLLCKSELR_DIVM2_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM2_Pos) +#define RCC_PLLCKSELR_DIVM3_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM3_Pos) + +#define RCC_PLL1DIVR_DIVN1_VALUE(n) ((n) << RCC_PLL1DIVR_N1) +#define RCC_PLL1DIVR_DIVP1_VALUE(n) ((n) << RCC_PLL1DIVR_P1) +#define RCC_PLL1DIVR_DIVQ1_VALUE(n) ((n) << RCC_PLL1DIVR_Q1) +#define RCC_PLL1DIVR_DIVR1_VALUE(n) ((n) << RCC_PLL1DIVR_R1) + +#define RCC_PLL1FRACR_FRACN1_VALUE(n) ((n) << RCC_PLL1FRACR_FRACN1_Pos) + +#define RCC_PLL2DIVR_DIVN2_VALUE(n) ((n) << RCC_PLL2DIVR_N2) +#define RCC_PLL2DIVR_DIVP2_VALUE(n) ((n) << RCC_PLL2DIVR_P2) +#define RCC_PLL2DIVR_DIVQ2_VALUE(n) ((n) << RCC_PLL2DIVR_Q2) +#define RCC_PLL2DIVR_DIVR2_VALUE(n) ((n) << RCC_PLL2DIVR_R2) + +#define RCC_PLL2FRACR_FRACN2_VALUE(n) ((n) << RCC_PLL2FRACR_FRACN2_Pos) + +#define RCC_PLL3DIVR_DIVN3_VALUE(n) ((n) << RCC_PLL3DIVR_N3) +#define RCC_PLL3DIVR_DIVP3_VALUE(n) ((n) << RCC_PLL3DIVR_P3) +#define RCC_PLL3DIVR_DIVQ3_VALUE(n) ((n) << RCC_PLL3DIVR_Q3) +#define RCC_PLL3DIVR_DIVR3_VALUE(n) ((n) << RCC_PLL3DIVR_R3) + +#define RCC_PLL3FRACR_FRACN3_VALUE(n) ((n) << RCC_PLL3FRACR_FRACN3_Pos) + +#define RCC_D1CCIPR_CKPERSEL_VALUE(n) ((n) << RCC_D1CCIPR_CKPERSEL_Pos) +#define RCC_D1CCIPR_SDMMCSEL_VALUE(n) ((n) << RCC_D1CCIPR_SDMMCSEL_Pos) +#define RCC_D1CCIPR_QSPISEL_VALUE(n) ((n) << RCC_D1CCIPR_QSPISEL_Pos) +#define RCC_D1CCIPR_FMCSEL_VALUE(n) ((n) << RCC_D1CCIPR_FMCSEL_Pos) + +#define RCC_D2CCIP1R_SWPSEL_VALUE(n) ((n) << RCC_D2CCIP1R_SWPSEL_Pos) +#define RCC_D2CCIP1R_FDCANSEL_VALUE(n) ((n) << RCC_D2CCIP1R_FDCANSEL_Pos) +#define RCC_D2CCIP1R_DFSDM1SEL_VALUE(n) ((n) << RCC_D2CCIP1R_DFSDM1SEL_Pos) +#define RCC_D2CCIP1R_SPDIFSEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPDIFSEL_Pos) +#define RCC_D2CCIP1R_SPI45SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPI45SEL_Pos) +#define RCC_D2CCIP1R_SPI123SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPI123SEL_Pos) +#define RCC_D2CCIP1R_SAI23SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SAI23SEL_Pos) +#define RCC_D2CCIP1R_SAI1SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SAI1SEL_Pos) + +#define RCC_D2CCIP2R_LPTIM1SEL_VALUE(n) ((n) << RCC_D2CCIP2R_LPTIM1SEL_Pos) +#define RCC_D2CCIP2R_CECSEL_VALUE(n) ((n) << RCC_D2CCIP2R_CECSEL_Pos) +#define RCC_D2CCIP2R_USBSEL_VALUE(n) ((n) << RCC_D2CCIP2R_USBSEL_Pos) +#define RCC_D2CCIP2R_I2C123SEL_VALUE(n) ((n) << RCC_D2CCIP2R_I2C123SEL_Pos) +#define RCC_D2CCIP2R_RNGSEL_VALUE(n) ((n) << RCC_D2CCIP2R_RNGSEL_Pos) +#define RCC_D2CCIP2R_USART16SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART16SEL_Pos) +#define RCC_D2CCIP2R_USART234578SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART28SEL_Pos) + +#define RCC_D3CCIPR_SPI6SEL_VALUE(n) ((n) << RCC_D3CCIPR_SPI6SEL_Pos) +#define RCC_D3CCIPR_SAI4BSEL_VALUE(n) ((n) << RCC_D3CCIPR_SAI4BSEL_Pos) +#define RCC_D3CCIPR_SAI4ASEL_VALUE(n) ((n) << RCC_D3CCIPR_SAI4ASEL_Pos) +#define RCC_D3CCIPR_ADCSEL_VALUE(n) ((n) << RCC_D3CCIPR_ADCSEL_Pos) +#define RCC_D3CCIPR_LPTIM345SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPTIM345SEL_Pos) +#define RCC_D3CCIPR_LPTIM2SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPTIM2SEL_Pos) +#define RCC_D3CCIPR_I2C4SEL_VALUE(n) ((n) << RCC_D3CCIPR_I2C4SEL_Pos) +#define RCC_D3CCIPR_LPUART1SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPUART1SEL_Pos) + +#define RCC_BDCR_RTCSEL_VALUE(n) ((n) << RCC_BDCR_RTCSEL_Pos) +/** @} */ + +/** + * @name Configuration switches to be used in @p mcuconf.h + * @{ + */ +#define STM32_ODEN_DISABLED 0U +#define STM32_ODEN_ENABLED (SYSCFG_PWRCR_ODEN) + +#define STM32_VOS_SCALE3 (PWR_D3CR_VOS_0) +#define STM32_VOS_SCALE2 (PWR_D3CR_VOS_1) +#define STM32_VOS_SCALE1 (PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0) + +#define STM32_SW_HSI_CK RCC_CFGR_SW_VALUE(0U) +#define STM32_SW_CSI_CK RCC_CFGR_SW_VALUE(1U) +#define STM32_SW_HSE_CK RCC_CFGR_SW_VALUE(2U) +#define STM32_SW_PLL1_P_CK RCC_CFGR_SW_VALUE(3U) + +#define STM32_D1CPRE_DIV1 RCC_D1CFGR_D1CPRE_VALUE(0U) +#define STM32_D1CPRE_DIV2 RCC_D1CFGR_D1CPRE_VALUE(8U) +#define STM32_D1CPRE_DIV4 RCC_D1CFGR_D1CPRE_VALUE(9U) +#define STM32_D1CPRE_DIV8 RCC_D1CFGR_D1CPRE_VALUE(10U) +#define STM32_D1CPRE_DIV16 RCC_D1CFGR_D1CPRE_VALUE(11U) +#define STM32_D1CPRE_DIV64 RCC_D1CFGR_D1CPRE_VALUE(12U) +#define STM32_D1CPRE_DIV128 RCC_D1CFGR_D1CPRE_VALUE(13U) +#define STM32_D1CPRE_DIV256 RCC_D1CFGR_D1CPRE_VALUE(14U) +#define STM32_D1CPRE_DIV512 RCC_D1CFGR_D1CPRE_VALUE(15U) + +#define STM32_D1HPRE_DIV1 RCC_D1CFGR_D1HPRE_VALUE(0U) +#define STM32_D1HPRE_DIV2 RCC_D1CFGR_D1HPRE_VALUE(8U) +#define STM32_D1HPRE_DIV4 RCC_D1CFGR_D1HPRE_VALUE(9U) +#define STM32_D1HPRE_DIV8 RCC_D1CFGR_D1HPRE_VALUE(10U) +#define STM32_D1HPRE_DIV16 RCC_D1CFGR_D1HPRE_VALUE(11U) +#define STM32_D1HPRE_DIV64 RCC_D1CFGR_D1HPRE_VALUE(12U) +#define STM32_D1HPRE_DIV128 RCC_D1CFGR_D1HPRE_VALUE(13U) +#define STM32_D1HPRE_DIV256 RCC_D1CFGR_D1HPRE_VALUE(14U) +#define STM32_D1HPRE_DIV512 RCC_D1CFGR_D1HPRE_VALUE(15U) + +#define STM32_D1PPRE3_DIV1 RCC_D1CFGR_D1PPRE3_VALUE(0U) +#define STM32_D1PPRE3_DIV2 RCC_D1CFGR_D1PPRE3_VALUE(4U) +#define STM32_D1PPRE3_DIV4 RCC_D1CFGR_D1PPRE3_VALUE(5U) +#define STM32_D1PPRE3_DIV8 RCC_D1CFGR_D1PPRE3_VALUE(6U) +#define STM32_D1PPRE3_DIV16 RCC_D1CFGR_D1PPRE3_VALUE(7U) + +#define STM32_D2PPRE1_DIV1 RCC_D2CFGR_D2PPRE1_VALUE(0U) +#define STM32_D2PPRE1_DIV2 RCC_D2CFGR_D2PPRE1_VALUE(4U) +#define STM32_D2PPRE1_DIV4 RCC_D2CFGR_D2PPRE1_VALUE(5U) +#define STM32_D2PPRE1_DIV8 RCC_D2CFGR_D2PPRE1_VALUE(6U) +#define STM32_D2PPRE1_DIV16 RCC_D2CFGR_D2PPRE1_VALUE(7U) + +#define STM32_D2PPRE2_DIV1 RCC_D2CFGR_D2PPRE2_VALUE(0U) +#define STM32_D2PPRE2_DIV2 RCC_D2CFGR_D2PPRE2_VALUE(4U) +#define STM32_D2PPRE2_DIV4 RCC_D2CFGR_D2PPRE2_VALUE(5U) +#define STM32_D2PPRE2_DIV8 RCC_D2CFGR_D2PPRE2_VALUE(6U) +#define STM32_D2PPRE2_DIV16 RCC_D2CFGR_D2PPRE2_VALUE(7U) + +#define STM32_D3PPRE4_DIV1 RCC_D3CFGR_D3PPRE4_VALUE(0U) +#define STM32_D3PPRE4_DIV2 RCC_D3CFGR_D3PPRE4_VALUE(4U) +#define STM32_D3PPRE4_DIV4 RCC_D3CFGR_D3PPRE4_VALUE(5U) +#define STM32_D3PPRE4_DIV8 RCC_D3CFGR_D3PPRE4_VALUE(6U) +#define STM32_D3PPRE4_DIV16 RCC_D3CFGR_D3PPRE4_VALUE(7U) + +#define STM32_HSIDIV_DIV1 RCC_CR_HSIDIV_VALUE(0U) +#define STM32_HSIDIV_DIV2 RCC_CR_HSIDIV_VALUE(1U) +#define STM32_HSIDIV_DIV4 RCC_CR_HSIDIV_VALUE(2U) +#define STM32_HSIDIV_DIV8 RCC_CR_HSIDIV_VALUE(3U) + +#define STM32_MCO1SEL_HSI_CK RCC_CFGR_MCO1_VALUE(0U) +#define STM32_MCO1SEL_LSE_CK RCC_CFGR_MCO1_VALUE(1U) +#define STM32_MCO1SEL_HSE_CK RCC_CFGR_MCO1_VALUE(2U) +#define STM32_MCO1SEL_PLL1_Q_CK RCC_CFGR_MCO1_VALUE(3U) +#define STM32_MCO1SEL_HSI48_CK RCC_CFGR_MCO1_VALUE(4U) + +#define STM32_MCO2SEL_SYS_CK RCC_CFGR_MCO2_VALUE(0U) +#define STM32_MCO2SEL_PLL2_P_CK RCC_CFGR_MCO2_VALUE(1U) +#define STM32_MCO2SEL_HSE_CK RCC_CFGR_MCO2_VALUE(2U) +#define STM32_MCO2SEL_PLL1_P_CK RCC_CFGR_MCO2_VALUE(3U) +#define STM32_MCO2SEL_CSI_CK RCC_CFGR_MCO2_VALUE(4U) +#define STM32_MCO2SEL_LSI_CK RCC_CFGR_MCO2_VALUE(5U) + +#define STM32_RTCSEL_MASK RCC_BDCR_RTCSEL_Msk +#define STM32_RTCSEL_NOCLK RCC_BDCR_RTCSEL_VALUE(0U) +#define STM32_RTCSEL_LSE_CK RCC_BDCR_RTCSEL_VALUE(1U) +#define STM32_RTCSEL_LSI_CK RCC_BDCR_RTCSEL_VALUE(2U) +#define STM32_RTCSEL_HSE_1M_CK RCC_BDCR_RTCSEL_VALUE(3U) + +#define STM32_HRTIMSEL_C_CLK RCC_CFGR_HRTIMSEL + +#define STM32_STOPKERWUCK_ENABLED RCC_CFGR_STOPKERWUCK + +#define STM32_STOPWUCK_ENABLED RCC_CFGR_STOPKERWUCK + +#define STM32_PLLSRC_HSI_CK RCC_PLLCKSELR_PLLSRC_VALUE(0U) +#define STM32_PLLSRC_CSI_CK RCC_PLLCKSELR_PLLSRC_VALUE(1U) +#define STM32_PLLSRC_HSE_CK RCC_PLLCKSELR_PLLSRC_VALUE(2U) +#define STM32_PLLSRC_DISABLE RCC_PLLCKSELR_PLLSRC_VALUE(23U) + +#define STM32_CKPERSEL_HSI_CK RCC_D1CCIPR_CKPERSEL_VALUE(0U) +#define STM32_CKPERSEL_CSI_CK RCC_D1CCIPR_CKPERSEL_VALUE(1U) +#define STM32_CKPERSEL_HSE_CK RCC_D1CCIPR_CKPERSEL_VALUE(2U) + +#define STM32_SDMMCSEL_PLL1_Q_CK RCC_D1CCIPR_SDMMCSEL_VALUE(0U) +#define STM32_SDMMCSEL_PLL2_R_CK RCC_D1CCIPR_SDMMCSEL_VALUE(1U) + +#define STM32_QSPISEL_HCLK RCC_D1CCIPR_QSPISEL_VALUE(0U) +#define STM32_QSPISEL_PLL1_Q_CK RCC_D1CCIPR_QSPISEL_VALUE(1U) +#define STM32_QSPISEL_PLL2_R_CK RCC_D1CCIPR_QSPISEL_VALUE(2U) +#define STM32_QSPISEL_PER_CK RCC_D1CCIPR_QSPISEL_VALUE(3U) + +#define STM32_FMCSEL_HCLK RCC_D1CCIPR_FMCSEL_VALUE(0U) +#define STM32_FMCSEL_PLL1_Q_CK RCC_D1CCIPR_FMCSEL_VALUE(1U) +#define STM32_FMCSEL_PLL2_R_CK RCC_D1CCIPR_FMCSEL_VALUE(2U) +#define STM32_FMCSEL_PER_CK RCC_D1CCIPR_FMCSEL_VALUE(3U) + +#define STM32_SWPSEL_PCLK1 RCC_D2CCIP1R_SWPSEL_VALUE(0U) +#define STM32_SWPSEL_HSI_KER_CK RCC_D2CCIP1R_SWPSEL_VALUE(1U) + +#define STM32_FDCANSEL_HSE_CK RCC_D2CCIP1R_FDCANSEL_VALUE(0U) +#define STM32_FDCANSEL_PLL1_Q_CK RCC_D2CCIP1R_FDCANSEL_VALUE(1U) +#define STM32_FDCANSEL_PLL2_Q_CK RCC_D2CCIP1R_FDCANSEL_VALUE(2U) + +#define STM32_DFSDM1SEL_PCLK2 RCC_D2CCIP1R_DFSDM1SEL_VALUE(0U) +#define STM32_DFSDM1SEL_SYS_CK RCC_D2CCIP1R_DFSDM1SEL_VALUE(1U) + +#define STM32_SPDIFSEL_PLL1_Q_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(0U) +#define STM32_SPDIFSEL_PLL2_R_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(1U) +#define STM32_SPDIFSEL_PLL3_R_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(2U) +#define STM32_SPDIFSEL_HSI_KET_CLK RCC_D2CCIP1R_SPDIFSEL_VALUE(3U) + +#define STM32_SPI45SEL_PCLK2 RCC_D2CCIP1R_SPI45SEL_VALUE(0U) +#define STM32_SPI45SEL_PLL2_Q_CK RCC_D2CCIP1R_SPI45SEL_VALUE(1U) +#define STM32_SPI45SEL_PLL3_Q_CK RCC_D2CCIP1R_SPI45SEL_VALUE(2U) +#define STM32_SPI45SEL_HSI_KER_CK RCC_D2CCIP1R_SPI45SEL_VALUE(3U) +#define STM32_SPI45SEL_CSI_KER_CK RCC_D2CCIP1R_SPI45SEL_VALUE(4U) +#define STM32_SPI45SEL_HSE_CK RCC_D2CCIP1R_SPI45SEL_VALUE(5U) + +#define STM32_SPI123SEL_PLL1_Q_CK RCC_D2CCIP1R_SPI123SEL_VALUE(0U) +#define STM32_SPI123SEL_PLL2_P_CK RCC_D2CCIP1R_SPI123SEL_VALUE(1U) +#define STM32_SPI123SEL_PLL3_P_CK RCC_D2CCIP1R_SPI123SEL_VALUE(2U) +#define STM32_SPI123SEL_I2S_CKIN RCC_D2CCIP1R_SPI123SEL_VALUE(3U) +#define STM32_SPI123SEL_PER_CK RCC_D2CCIP1R_SPI123SEL_VALUE(4U) + +#define STM32_SAI23SEL_PLL1_Q_CK RCC_D2CCIP1R_SAI23SEL_VALUE(0U) +#define STM32_SAI23SEL_PLL2_P_CK RCC_D2CCIP1R_SAI23SEL_VALUE(1U) +#define STM32_SAI23SEL_PLL3_P_CK RCC_D2CCIP1R_SAI23SEL_VALUE(2U) +#define STM32_SAI23SEL_I2S_CKIN RCC_D2CCIP1R_SAI23SEL_VALUE(3U) +#define STM32_SAI23SEL_PER_CK RCC_D2CCIP1R_SAI23SEL_VALUE(4U) + +#define STM32_SAI1SEL_PLL1_Q_CK RCC_D2CCIP1R_SAI1SEL_VALUE(0U) +#define STM32_SAI1SEL_PLL2_P_CK RCC_D2CCIP1R_SAI1SEL_VALUE(1U) +#define STM32_SAI1SEL_PLL3_P_CK RCC_D2CCIP1R_SAI1SEL_VALUE(2U) +#define STM32_SAI1SEL_I2S_CKIN RCC_D2CCIP1R_SAI1SEL_VALUE(3U) +#define STM32_SAI1SEL_PER_CK RCC_D2CCIP1R_SAI1SEL_VALUE(4U) + +#define STM32_LPTIM1SEL_PCLK1 RCC_D2CCIP2R_LPTIM1SEL_VALUE(0U) +#define STM32_LPTIM1SEL_PLL2_P_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(1U) +#define STM32_LPTIM1SEL_PLL3_R_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(2U) +#define STM32_LPTIM1SEL_LSE_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(3U) +#define STM32_LPTIM1SEL_LSI_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(4U) +#define STM32_LPTIM1SEL_PER_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(5U) + +#define STM32_CECSEL_LSE_CK RCC_D2CCIP2R_CECSEL_VALUE(0U) +#define STM32_CECSEL_LSI_CK RCC_D2CCIP2R_CECSEL_VALUE(1U) +#define STM32_CECSEL_CSI_KER_CK RCC_D2CCIP2R_CECSEL_VALUE(2U) +#define STM32_CECSEL_DISABLE RCC_D2CCIP2R_CECSEL_VALUE(3U) + +#define STM32_USBSEL_DISABLE RCC_D2CCIP2R_USBSEL_VALUE(0U) +#define STM32_USBSEL_PLL1_Q_CK RCC_D2CCIP2R_USBSEL_VALUE(1U) +#define STM32_USBSEL_PLL3_Q_CK RCC_D2CCIP2R_USBSEL_VALUE(2U) +#define STM32_USBSEL_HSI48_CK RCC_D2CCIP2R_USBSEL_VALUE(3U) + +#define STM32_I2C123SEL_PCLK1 RCC_D2CCIP2R_I2C123SEL_VALUE(0U) +#define STM32_I2C123SEL_PLL3_R_CK RCC_D2CCIP2R_I2C123SEL_VALUE(1U) +#define STM32_I2C123SEL_HSI_KER_CK RCC_D2CCIP2R_I2C123SEL_VALUE(2U) +#define STM32_I2C123SEL_CSI_KER_CK RCC_D2CCIP2R_I2C123SEL_VALUE(3U) + +#define STM32_RNGSEL_HSI48_CK RCC_D2CCIP2R_RNGSEL_VALUE(0U) +#define STM32_RNGSEL_PLL1_Q_CK RCC_D2CCIP2R_RNGSEL_VALUE(1U) +#define STM32_RNGSEL_LSE_CK RCC_D2CCIP2R_RNGSEL_VALUE(2U) +#define STM32_RNGSEL_LSI_CK RCC_D2CCIP2R_RNGSEL_VALUE(3U) + +#define STM32_USART16SEL_PCLK2 RCC_D2CCIP2R_USART16SEL_VALUE(0U) +#define STM32_USART16SEL_PLL2_Q_CK RCC_D2CCIP2R_USART16SEL_VALUE(1U) +#define STM32_USART16SEL_PLL3_Q_CK RCC_D2CCIP2R_USART16SEL_VALUE(2U) +#define STM32_USART16SEL_HSI_KER_CK RCC_D2CCIP2R_USART16SEL_VALUE(3U) +#define STM32_USART16SEL_CSI_KER_CK RCC_D2CCIP2R_USART16SEL_VALUE(4U) +#define STM32_USART16SEL_LSE_CK RCC_D2CCIP2R_USART16SEL_VALUE(5U) + +#define STM32_USART234578SEL_PCLK1 RCC_D2CCIP2R_USART234578SEL_VALUE(0U) +#define STM32_USART234578SEL_PLL2_Q_CK RCC_D2CCIP2R_USART234578SEL_VALUE(1U) +#define STM32_USART234578SEL_PLL3_Q_CK RCC_D2CCIP2R_USART234578SEL_VALUE(2U) +#define STM32_USART234578SEL_HSI_KER_CK RCC_D2CCIP2R_USART234578SEL_VALUE(3U) +#define STM32_USART234578SEL_CSI_KER_CK RCC_D2CCIP2R_USART234578SEL_VALUE(4U) +#define STM32_USART234578SEL_LSE_CK RCC_D2CCIP2R_USART234578SEL_VALUE(5U) + +#define STM32_SPI6SEL_PCLK4 RCC_D3CCIPR_SPI6SEL_VALUE(0U) +#define STM32_SPI6SEL_PLL2_Q_CK RCC_D3CCIPR_SPI6SEL_VALUE(1U) +#define STM32_SPI6SEL_PLL3_Q_CK RCC_D3CCIPR_SPI6SEL_VALUE(2U) +#define STM32_SPI6SEL_HSI_KER_CK RCC_D3CCIPR_SPI6SEL_VALUE(3U) +#define STM32_SPI6SEL_CSI_KER_CK RCC_D3CCIPR_SPI6SEL_VALUE(4U) +#define STM32_SPI6SEL_HSE_CK RCC_D3CCIPR_SPI6SEL_VALUE(5U) + +#define STM32_SAI4BSEL_PLL1_Q_CK RCC_D3CCIPR_SAI4BSEL_VALUE(0U) +#define STM32_SAI4BSEL_PLL2_P_CK RCC_D3CCIPR_SAI4BSEL_VALUE(1U) +#define STM32_SAI4BSEL_PLL3_P_CK RCC_D3CCIPR_SAI4BSEL_VALUE(2U) +#define STM32_SAI4BSEL_I2S_CKIN RCC_D3CCIPR_SAI4BSEL_VALUE(3U) +#define STM32_SAI4BSEL_PER_CK RCC_D3CCIPR_SAI4BSEL_VALUE(4U) + +#define STM32_SAI4ASEL_PLL1_Q_CK RCC_D3CCIPR_SAI4ASEL_VALUE(0U) +#define STM32_SAI4ASEL_PLL2_P_CK RCC_D3CCIPR_SAI4ASEL_VALUE(1U) +#define STM32_SAI4ASEL_PLL3_P_CK RCC_D3CCIPR_SAI4ASEL_VALUE(2U) +#define STM32_SAI4ASEL_I2S_CKIN RCC_D3CCIPR_SAI4ASEL_VALUE(3U) +#define STM32_SAI4ASEL_PER_CK RCC_D3CCIPR_SAI4ASEL_VALUE(4U) + +#define STM32_ADCSEL_PLL2_P_CK RCC_D3CCIPR_ADCSEL_VALUE(0U) +#define STM32_ADCSEL_PLL3_R_CK RCC_D3CCIPR_ADCSEL_VALUE(1U) +#define STM32_ADCSEL_PER_CK RCC_D3CCIPR_ADCSEL_VALUE(2U) +#define STM32_ADCSEL_DISABLE RCC_D3CCIPR_ADCSEL_VALUE(3U) + +#define STM32_LPTIM345SEL_PCLK4 RCC_D3CCIPR_LPTIM345SEL_VALUE(0U) +#define STM32_LPTIM345SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(1U) +#define STM32_LPTIM345SEL_PLL3_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(2U) +#define STM32_LPTIM345SEL_LSE_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(3U) +#define STM32_LPTIM345SEL_LSI_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(4U) +#define STM32_LPTIM345SEL_PER_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(5U) + +#define STM32_LPTIM2SEL_PCLK4 RCC_D3CCIPR_LPTIM2SEL_VALUE(0U) +#define STM32_LPTIM2SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(1U) +#define STM32_LPTIM2SEL_PLL3_P_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(2U) +#define STM32_LPTIM2SEL_LSE_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(3U) +#define STM32_LPTIM2SEL_LSI_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(4U) +#define STM32_LPTIM2SEL_PER_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(5U) + +#define STM32_I2C4SEL_PCLK4 RCC_D3CCIPR_I2C4SEL_VALUE(0U) +#define STM32_I2C4SEL_PLL3_R_CK RCC_D3CCIPR_I2C4SEL_VALUE(1U) +#define STM32_I2C4SEL_HSI_KER_CK RCC_D3CCIPR_I2C4SEL_VALUE(2U) +#define STM32_I2C4SEL_CSI_KER_CK RCC_D3CCIPR_I2C4SEL_VALUE(3U) + +#define STM32_LPUART1SEL_PCLK4 RCC_D3CCIPR_LPUART1SEL_VALUE(0U) +#define STM32_LPUART1SEL_PLL2_Q_CK RCC_D3CCIPR_LPUART1SEL_VALUE(1U) +#define STM32_LPUART1SEL_PLL3_Q_CK RCC_D3CCIPR_LPUART1SEL_VALUE(2U) +#define STM32_LPUART1SEL_HSI_KER_CK RCC_D3CCIPR_LPUART1SEL_VALUE(3U) +#define STM32_LPUART1SEL_CSI_KER_CK RCC_D3CCIPR_LPUART1SEL_VALUE(4U) +#define STM32_LPUART1SEL_LSE_CK RCC_D3CCIPR_LPUART1SEL_VALUE(5U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + * @note All the clock tree constants are calculated but the initialization + * is not performed. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Target code for this HAL configuration. + * @note Core 1 is the Cortex-M7, core 2 is the Cortex-M4. + */ +#if !defined(STM32_TARGET_CORE) || defined(__DOXYGEN__) +#define STM32_TARGET_CORE 1 +#endif + +/** + * @brief MPU region to be used for no-cache RAM area. + */ +#if !defined(STM32_NOCACHE_MPU_REGION) || defined(__DOXYGEN__) +#define STM32_NOCACHE_MPU_REGION MPU_REGION_6 +#endif + +/** + * @brief Add no-cache attribute to SRAM1 and SRAM2. + * @note MPU region 7 is used if enabled. + */ +#if !defined(STM32_NOCACHE_SRAM1_SRAM2) || defined(__DOXYGEN__) +#define STM32_NOCACHE_SRAM1_SRAM2 FALSE +#endif + +/** + * @brief Add no-cache attribute to SRAM3. + * @note MPU region 7 is used if enabled. + */ +#if !defined(STM32_NOCACHE_SRAM3) || defined(__DOXYGEN__) +#define STM32_NOCACHE_SRAM3 TRUE +#endif + +/** + * @brief PWR CR1 initializer. + */ +#if !defined(STM32_PWR_CR1) || defined(__DOXYGEN__) +#define STM32_PWR_CR1 (PWR_CR1_SVOS_1 | \ + PWR_CR1_SVOS_0) +#endif + +/** + * @brief PWR CR2 initializer. + */ +#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__) +#define STM32_PWR_CR2 (PWR_CR2_BREN) +#endif + +/** + * @brief PWR CR3 initializer. + */ +#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__) +#define STM32_PWR_CR3 (PWR_CR3_LDOEN | \ + PWR_CR3_USBREGEN | \ + PWR_CR3_USB33DEN) +#endif + +/** + * @brief PWR CPUCR initializer. + */ +#if !defined(STM32_PWR_CPUCR) || defined(__DOXYGEN__) +#define STM32_PWR_CPUCR 0 +#endif + +/** + * @brief VOS setting. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_SCALE1 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_CSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_CSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSI48 clock source. + */ +#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI48_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED TRUE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE_CK +#endif + +/** + * @brief HSI divider. + */ +#if !defined(STM32_HSIDIV) || defined(__DOXYGEN__) +#define STM32_HSIDIV STM32_HSIDIV_DIV1 +#endif + +/** + * @brief Clock source for all PLLs. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE_CK +#endif + +/** + * @brief Masking of PLLCFGR register. + * @note By default all options in PLLCFGR are enabled, this option + * allows to mask specific bits for power saving reasons. + * Use with caution. + */ +#if !defined(STM32_PLLCFGR_MASK) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_MASK ~0 +#endif + +/** + * @brief Enables or disables the PLL1. + */ +#if !defined(STM32_PLL1_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL1_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL1 P output. + */ +#if !defined(STM32_PLL1_P_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL1_P_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL1 Q output. + */ +#if !defined(STM32_PLL1_Q_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL1_Q_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL1 R output. + */ +#if !defined(STM32_PLL1_R_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL1_R_ENABLED TRUE +#endif + +/** + * @brief PLL1 DIVM divider. + * @note The allowed values are 1..63. + */ +#if !defined(STM32_PLL1_DIVM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL1_DIVM_VALUE 4 +#endif + +/** + * @brief PLL1 DIVN multiplier. + * @note The allowed values are 4..512. + */ +#if !defined(STM32_PLL1_DIVN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL1_DIVN_VALUE 400 +#endif + +/** + * @brief PLL1 FRACN multiplier, zero if no fractional part. + * @note The allowed values are 0..8191. + */ +#if !defined(STM32_PLL1_FRACN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL1_FRACN_VALUE 0 +#endif + +/** + * @brief PLL1 DIVP divider. + * @note The allowed values are 2..128, odd values not allowed. + */ +#if !defined(STM32_PLL1_DIVP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL1_DIVP_VALUE 2 +#endif + +/** + * @brief PLL1 DIVQ divider. + * @note The allowed values are 1..128. + */ +#if !defined(STM32_PLL1_DIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL1_DIVQ_VALUE 8 +#endif + +/** + * @brief PLL1 DIVR divider. + * @note The allowed values are 1..128. + */ +#if !defined(STM32_PLL1_DIVR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL1_DIVR_VALUE 8 +#endif + +/** + * @brief Enables or disables the PLL2. + */ +#if !defined(STM32_PLL2_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL2_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL2 P output. + */ +#if !defined(STM32_PLL2_P_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL1_2_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL2 Q output. + */ +#if !defined(STM32_PLL2_Q_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL2_Q_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL2 R output. + */ +#if !defined(STM32_PLL2_R_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL2_R_ENABLED TRUE +#endif + +/** + * @brief PLL2 DIVM divider. + * @note The allowed values are 1..63. + */ +#if !defined(STM32_PLL2_DIVM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2_DIVM_VALUE 4 +#endif + +/** + * @brief PLL2 DIVN multiplier. + * @note The allowed values are 4..512. + */ +#if !defined(STM32_PLL2_DIVN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2_DIVN_VALUE 400 +#endif + +/** + * @brief PLL2 FRACN multiplier, zero if no fractional part. + * @note The allowed values are 0..8191. + */ +#if !defined(STM32_PLL2_FRACN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2_FRACN_VALUE 0 +#endif + +/** + * @brief PLL2 DIVP divider. + * @note The allowed values are 2..128, odd values not allowed. + */ +#if !defined(STM32_PLL2_DIVP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2_DIVP_VALUE 40 +#endif + +/** + * @brief PLL2 DIVQ divider. + * @note The allowed values are 1..128. + */ +#if !defined(STM32_PLL2_DIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2_DIVQ_VALUE 8 +#endif + +/** + * @brief PLL2 DIVR divider. + * @note The allowed values are 1..128. + */ +#if !defined(STM32_PLL2_DIVR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL2_DIVR_VALUE 8 +#endif + +/** + * @brief Enables or disables the PLL3. + */ +#if !defined(STM32_PLL3_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL3_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL3 P output. + */ +#if !defined(STM32_PLL3_P_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL3_P_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL3 Q output. + */ +#if !defined(STM32_PLL3_Q_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL3_Q_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the PLL3 R output. + */ +#if !defined(STM32_PLL3_R_ENABLED) || defined(__DOXYGEN__) +#define STM32_PLL3_R_ENABLED TRUE +#endif + +/** + * @brief PLL3 DIVM divider. + * @note The allowed values are 1..63. + */ +#if !defined(STM32_PLL3_DIVM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3_DIVM_VALUE 4 +#endif + +/** + * @brief PLL3 DIVN multiplier. + * @note The allowed values are 4..512. + */ +#if !defined(STM32_PLL3_DIVN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3_DIVN_VALUE 400 +#endif + +/** + * @brief PLL3 FRACN multiplier, zero if no fractional part. + * @note The allowed values are 0..8191. + */ +#if !defined(STM32_PLL3_FRACN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3_FRACN_VALUE 0 +#endif + +/** + * @brief PLL3 DIVP divider. + * @note The allowed values are 2..128, odd values not allowed. + */ +#if !defined(STM32_PLL3_DIVP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3_DIVP_VALUE 8 +#endif + +/** + * @brief PLL3 DIVQ divider. + * @note The allowed values are 1..128. + */ +#if !defined(STM32_PLL3_DIVQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3_DIVQ_VALUE 8 +#endif + +/** + * @brief PLL3 DIVR divider. + * @note The allowed values are 1..128. + */ +#if !defined(STM32_PLL3_DIVR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLL3_DIVR_VALUE 8 +#endif + +/** + * @brief Peripherals clock selector. + */ +#if !defined(STM32_CKPERSEL) || defined(__DOXYGEN__) +#define STM32_CKPERSEL STM32_CKPERSEL_HSE_CK +#endif + +/** + * @brief MCO1 clock selector. + */ +#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) +#define STM32_MCO1SEL STM32_MCO1SEL_HSI_CK +#endif + +/** + * @brief MCO1 clock prescaler. + */ +#if !defined(STM32_MCO1PRE_VALUE) || defined(__DOXYGEN__) +#define STM32_MCO1PRE_VALUE 4 +#endif + +/** + * @brief MCO2 clock selector. + */ +#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) +#define STM32_MCO2SEL STM32_MCO2SEL_SYS_CK +#endif + +/** + * @brief MCO2 clock prescaler. + */ +#if !defined(STM32_MCO2PRE_VALUE) || defined(__DOXYGEN__) +#define STM32_MCO2PRE_VALUE 4 +#endif + +/** + * @brief TIM clock prescaler selection. + */ +#if !defined(STM32_TIMPRE_ENABLE) || defined(__DOXYGEN__) +#define STM32_TIMPRE_ENABLE FALSE +#endif + +/** + * @brief HRTIM clock prescaler selection. + */ +#if !defined(STM32_HRTIMSEL) || defined(__DOXYGEN__) +#define STM32_HRTIMSEL 0 +#endif + +/** + * @brief Kernel clock selection after a wake up from system Stop. + */ +#if !defined(STM32_STOPKERWUCK) || defined(__DOXYGEN__) +#define STM32_STOPKERWUCK 0 +#endif + +/** + * @brief System clock selection after a wake up from system Stop. + */ +#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) +#define STM32_STOPWUCK 0 +#endif + +/** + * @brief RTC HSE prescaler value. + * @note The allowed values are 2..63. + */ +#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) +#define STM32_RTCPRE_VALUE 8 +#endif + +/** + * @brief Main clock source selection. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL1_P_CK1_P_CK +#endif + +/** + * @brief RTC clock selector. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSE_CK +#endif + +/** + * @brief Clock domain 1 core bus prescaler. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_D1CPRE) || defined(__DOXYGEN__) +#define STM32_D1CPRE STM32_D1CPRE_DIV1 +#endif + +/** + * @brief Clock domain 1 HPRE prescaler. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_D1HPRE) || defined(__DOXYGEN__) +#define STM32_D1HPRE STM32_D1HPRE_DIV4 +#endif + +/** + * @brief Clock domain 1 peripherals bus prescaler. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_D1PPRE3) || defined(__DOXYGEN__) +#define STM32_D1PPRE3 STM32_D1PPRE3_DIV1 +#endif + +/** + * @brief Clock domain 2 peripherals bus 1 prescaler. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_D2PPRE1) || defined(__DOXYGEN__) +#define STM32_D2PPRE1 STM32_D2PPRE1_DIV1 +#endif + +/** + * @brief Clock domain 2 peripherals bus 2 prescaler. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_D2PPRE2) || defined(__DOXYGEN__) +#define STM32_D2PPRE2 STM32_D2PPRE2_DIV1 +#endif + +/** + * @brief Clock domain 3 peripherals bus prescaler. + * @note This setting can be modified at runtime. + */ +#if !defined(STM32_D3PPRE4) || defined(__DOXYGEN__) +#define STM32_D3PPRE4 STM32_D3PPRE4_DIV1 +#endif + +/** + * @brief SDMMC clock source. + */ +#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__) +#define STM32_SDMMCSEL STM32_SDMMCSEL_PLL1_Q_CK +#endif + +/** + * @brief QSPI clock source. + */ +#if !defined(STM32_QSPISEL) || defined(__DOXYGEN__) +#define STM32_QSPISEL STM32_QSPISEL_HCLK +#endif + +/** + * @brief FMC clock source. + */ +#if !defined(STM32_FMCSEL) || defined(__DOXYGEN__) +#define STM32_FMCSEL STM32_QSPISEL_HCLK +#endif + +/** + * @brief SWP clock source. + */ +#if !defined(STM32_SWPSEL) || defined(__DOXYGEN__) +#define STM32_SWPSEL STM32_SWPSEL_PCLK1 +#endif + +/** + * @brief FDCAN clock source. + */ +#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__) +#define STM32_FDCANSEL STM32_FDCANSEL_HSE_CK +#endif + +/** + * @brief DFSDM1 clock source. + */ +#if !defined(STM32_DFSDM1SEL) || defined(__DOXYGEN__) +#define STM32_DFSDM1SEL STM32_DFSDM1SEL_PCLK2 +#endif + +/** + * @brief SPDIF clock source. + */ +#if !defined(STM32_SPDIFSEL) || defined(__DOXYGEN__) +#define STM32_SPDIFSEL STM32_SPDIFSEL_PLL1_Q_CK +#endif + +/** + * @brief SPI45 clock source. + */ +#if !defined(STM32_SPI45SEL) || defined(__DOXYGEN__) +#define STM32_SPI45SEL STM32_SPI45SEL_PCLK2 +#endif + +/** + * @brief SPI123 clock source. + */ +#if !defined(STM32_SPI123SEL) || defined(__DOXYGEN__) +#define STM32_SPI123SEL STM32_SPI123SEL_PLL1_Q_CK +#endif + +/** + * @brief SAI23 clock source. + */ +#if !defined(STM32_SAI23SEL) || defined(__DOXYGEN__) +#define STM32_SAI23SEL STM32_SAI23SEL_PLL1_Q_CK +#endif + +/** + * @brief SAI1 clock source. + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_PLL1_Q_CK +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1_PCLK1 +#endif + +/** + * @brief CEC clock source. + */ +#if !defined(STM32_CECSEL) || defined(__DOXYGEN__) +#define STM32_CECSEL STM32_CECSEL_LSE_CK +#endif + +/** + * @brief USB clock source. + */ +#if !defined(STM32_USBSEL) || defined(__DOXYGEN__) +#define STM32_USBSEL STM32_USBSEL_PLL3_Q_CK +#endif + +/** + * @brief I2C123 clock source. + */ +#if !defined(STM32_I2C123SEL) || defined(__DOXYGEN__) +#define STM32_I2C123SEL STM32_I2C123SEL_PCLK1 +#endif + +/** + * @brief RNG clock source. + */ +#if !defined(STM32_RNGSEL) || defined(__DOXYGEN__) +#define STM32_RNGSEL STM32_RNGSEL_HSI48_CK +#endif + +/** + * @brief USART16 clock source. + */ +#if !defined(STM32_USART16SEL) || defined(__DOXYGEN__) +#define STM32_USART16SEL STM32_USART16SEL_PCLK2 +#endif + +/** + * @brief USART234578 clock source. + */ +#if !defined(STM32_USART234578SEL) || defined(__DOXYGEN__) +#define STM32_USART234578SEL STM32_USART234578SEL_PCLK1 +#endif + +/** + * @brief SPI6SEL clock source. + */ +#if !defined(STM32_SPI6SEL) || defined(__DOXYGEN__) +#define STM32_SPI6SEL STM32_SPI6SEL_PCLK4 +#endif + +/** + * @brief SAI4BSEL clock source. + */ +#if !defined(STM32_SAI4BSEL) || defined(__DOXYGEN__) +#define STM32_SAI4BSEL STM32_SAI4BSEL_PLL1_Q_CK +#endif + +/** + * @brief SAI4ASEL clock source. + */ +#if !defined(STM32_SAI4ASEL) || defined(__DOXYGEN__) +#define STM32_SAI4ASEL STM32_SAI4ASEL_PLL1_Q_CK +#endif + +/** + * @brief ADCSEL clock source. + */ +#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) +#define STM32_ADCSEL STM32_ADCSEL_PLL2_P_CK +#endif + +/** + * @brief LPTIM345SEL clock source. + */ +#if !defined(STM32_LPTIM345SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM345SEL STM32_LPTIM345SEL_PCLK4 +#endif + +/** + * @brief LPTIM2SEL clock source. + */ +#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK4 +#endif + +/** + * @brief I2C4SEL clock source. + */ +#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK4 +#endif + +/** + * @brief LPUART1SEL clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK4 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32H7xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H7xx_MCUCONF not defined" +#endif + +#if defined(STM32H750xx)&& !defined(STM32H750_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H750_MCUCONF not defined" +#endif + +#if defined(STM32H742xx)&& !defined(STM32H742_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H742_MCUCONF not defined" +#endif + +#if defined(STM32H743xx)&& !defined(STM32H743_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H743_MCUCONF not defined" +#endif + +#if defined(STM32H753xx)&& !defined(STM32H753_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H753_MCUCONF not defined" +#endif + +#if defined(STM32H745xx)&& !defined(STM32H745_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H745_MCUCONF not defined" +#endif + +#if defined(STM32H755xx)&& !defined(STM32H755_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H755_MCUCONF not defined" +#endif + +#if defined(STM32H747xx)&& !defined(STM32H747_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H747_MCUCONF not defined" +#endif + +#if defined(STM32H757xx)&& !defined(STM32H757_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32H757_MCUCONF not defined" +#endif + +/* + * Board file checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/** + * @name Constants depending on VOS and ODEN setting + * @{ + */ +#if STM32_VOS == STM32_VOS_SCALE1 +#define STM32_0WS_THRESHOLD 70000000U +#define STM32_1WS_THRESHOLD 140000000U +#define STM32_2WS_THRESHOLD 210000000U +#define STM32_3WS_THRESHOLD 225000000U +#define STM32_4WS_THRESHOLD 240000000U +#define STM32_PLLOUT_MAX 480000000U +#define STM32_PLLOUT_MIN 1500000U + +#elif STM32_VOS == STM32_VOS_SCALE2 +#define STM32_0WS_THRESHOLD 55000000U +#define STM32_1WS_THRESHOLD 110000000U +#define STM32_2WS_THRESHOLD 165000000U +#define STM32_3WS_THRESHOLD 225000000U +#define STM32_4WS_THRESHOLD 0U +#define STM32_PLLOUT_MAX 300000000U +#define STM32_PLLOUT_MIN 1500000U + +#elif STM32_VOS == STM32_VOS_SCALE3 +#define STM32_0WS_THRESHOLD 45000000U +#define STM32_1WS_THRESHOLD 90000000U +#define STM32_2WS_THRESHOLD 135000000U +#define STM32_3WS_THRESHOLD 180000000U +#define STM32_4WS_THRESHOLD 225000000U +#define STM32_PLLOUT_MAX 200000000U +#define STM32_PLLOUT_MIN 1500000U + +#else +#error "invalid STM32_VOS setting specified" +#endif +/** @} */ + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#define STM32_HSICLK STM32_HSI_OSC + +#else /* !STM32_HSI_ENABLED */ +#define STM32_HSICLK 0U + +#if STM32_SW == STM32_SW_HSI_CK +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_PLLSRC == STM32_PLLSRC_HSI_CK) && \ + (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED) +#error "HSI not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED" +#endif + +#if STM32_CKPERSEL == STM32_CKPERSEL_HSI_CK +#error "HSI not enabled, required by STM32_CKPERSEL" +#endif + +#if STM32_MCO1SEL == STM32_MCO1SEL_HSI_CK +#error "HSI not enabled, required by STM32_MCO1SEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSI48 related checks. + */ +#if STM32_HSI48_ENABLED +#define STM32_HSI48_CK STM32_HSI48_OSC + +#else /* !STM32_HSI48_ENABLED */ +#define STM32_HSI48_CK 0U + +#if STM32_MCO1SEL == STM32_MCO1SEL_HSI48_CK +#error "HSI48 not enabled, required by STM32_MCO1SEL" +#endif + +#endif /* !STM32_HSI48_ENABLED */ + +/* + * CSI related checks. + */ +#if STM32_CSI_ENABLED +#define STM32_CSI_CK STM32_CSI_OSC + +#else /* !STM32_CSI_ENABLED */ +#define STM32_CSI_CK 0U + +#if STM32_SW == STM32_SW_CSI_CK +#error "CSI not enabled, required by STM32_SW" +#endif + +#if (STM32_PLLSRC == STM32_PLLSRC_CSI_CK) && \ + (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED) +#error "CSI not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED" +#endif + +#if STM32_CKPERSEL == STM32_CKPERSEL_CSI_CK +#error "CSI not enabled, required by STM32_CKPERSEL" +#endif + +#if STM32_MCO2SEL == STM32_MCO2SEL_CSI_CK +#error "CSI not enabled, required by STM32_MCO2SEL" +#endif + +#endif /* !STM32_CSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if !defined(STM32_HSECLK) +#error "HSE frequency not defined" +#endif + +#define STM32_HSE_CK STM32_HSECLK + +#if STM32_HSECLK == 0 +#error "HSE oscllator not available" +#else /* STM32_HSECLK != 0 */ +#if defined(STM32_HSE_BYPASS) +#if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN..STM32_HSECLK_BYP_MAX)" +#endif +#else /* !defined(STM32_HSE_BYPASS) */ +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN..STM32_HSECLK_MAX)" +#endif +#endif /* !defined(STM32_HSE_BYPASS) */ +#endif /* STM32_HSECLK != 0 */ +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE_CK +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_PLLSRC == STM32_PLLSRC_HSE_CK) && \ + (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED) +#error "HSE not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED" +#endif + +#if STM32_MCO1SEL == STM32_MCO1SEL_HSE_CK +#error "HSE not enabled, required by STM32_MCO1SEL" +#endif + +#if STM32_MCO2SEL == STM32_MCO2SEL_HSE_CK +#error "HSE not enabled, required by STM32_MCO2SEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSE_1M_CK +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#define STM32_LSI_CK STM32_LSI_OSC + +#else /* !STM32_LSI_ENABLED */ +#define STM32_LSI_CK 0U + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI_CK) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#if STM32_MCO2SEL == STM32_MCO2SEL_LSI_CK +#error "HSE not enabled, required by STM32_MCO2SEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if !defined(STM32_LSECLK) +#error "LSE frequency not defined" +#endif + +#define STM32_LSE_CK STM32_LSECLK + +#if (STM32_LSE_CK == 0) +#error "LSE oscillator not available" +#endif + +#if defined(STM32_LSE_BYPASS) +#if (STM32_LSE_CK < STM32_LSE_CK_MIN) || (STM32_LSE_CK > STM32_LSE_CK_BYP_MAX) +#error "STM32_LSE_CK outside acceptable range (STM32_LSE_CK_MIN..STM32_LSE_CK_BYP_MAX)" +#endif +#else +#if (STM32_LSE_CK < STM32_LSE_CK_MIN) || (STM32_LSE_CK > STM32_LSE_CK_MAX) +#error "STM32_LSE_CK outside acceptable range (STM32_LSE_CK_MIN..STM32_LSE_CK_MAX)" +#endif +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)..(3<<3))" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE_CK +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#if STM32_MCO1SEL == STM32_MCO1SEL_LSE_CK +#error "LSE not enabled, required by STM32_MCO1SEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief HSI divided clock. + */ +#if (STM32_HSIDIV == STM32_HSIDIV_DIV1) || defined(__DOXYGEN__) +#define STM32_HSI_CK (STM32_HSICLK / 1U) +#elif STM32_HSIDIV == STM32_HSIDIV_DIV2 +#define STM32_HSI_CK (STM32_HSICLK / 2U) +#elif STM32_HSIDIV == STM32_HSIDIV_DIV4 +#define STM32_HSI_CK (STM32_HSICLK / 4U) +#elif STM32_HSIDIV == STM32_HSIDIV_DIV8 +#define STM32_HSI_CK (STM32_HSICLK / 8U) +#else +#error "invalid STM32_HSIDIV value specified" +#endif + +/** + * @brief HSE divided clock for RTC. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_HSE_1M_CK (STM32_HSE_CK / STM32_RTCPRE_VALUE) +#else +#error "invalid STM32_RTCPRE_VALUE value specified" +#endif + +/** + * @brief PLLs input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE_CK) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN STM32_HSE_CK + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI_CK +#define STM32_PLLCLKIN STM32_HSI_CK + +#elif STM32_PLLSRC == STM32_PLLSRC_CSI_CK +#define STM32_PLLCLKIN STM32_CSI_CK + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/** + * @brief PLL1 DIVM field. + */ +#if ((STM32_PLL1_DIVM_VALUE >= 1) && (STM32_PLL1_DIVM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLL1_DIVM (STM32_PLL1_DIVM_VALUE << 4) +#define STM32_PLL1_REF_CK (STM32_PLLCLKIN / STM32_PLL1_DIVM_VALUE) +#else +#error "invalid STM32_PLL1_DIVM_VALUE value specified" +#endif + +/* + * PLL1 input frequency range check. + */ +#if (STM32_PLL1_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL1_REF_CK > STM32_PLLIN_MAX) +#error "STM32_PLL1_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)" +#endif + +/** + * @brief PLL1 input range selector. + */ +#if (STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_0 +#elif STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD2 +#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_1 +#elif STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD3 +#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_2 +#else +#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_3 +#endif + +/** + * @brief PLL2 DIVM field. + */ +#if ((STM32_PLL2_DIVM_VALUE >= 1) && (STM32_PLL2_DIVM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2_DIVM (STM32_PLL2_DIVM_VALUE << 12) +#define STM32_PLL2_REF_CK (STM32_PLLCLKIN / STM32_PLL2_DIVM_VALUE) +#else +#error "invalid STM32_PLL2_DIVM_VALUE value specified" +#endif + +/* + * PLL2 input frequency range check. + */ +#if (STM32_PLL2_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL2_REF_CK > STM32_PLLIN_MAX) +#error "STM32_PLL2_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)" +#endif + +/** + * @brief PLL2 input range selector. + */ +#if (STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_0 +#elif STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD2 +#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_1 +#elif STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD3 +#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_2 +#else +#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_3 +#endif + +/** + * @brief PLL3 DIVM field. + */ +#if ((STM32_PLL3_DIVM_VALUE >= 1) && (STM32_PLL3_DIVM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3_DIVM (STM32_PLL3_DIVM_VALUE << 20) +#define STM32_PLL3_REF_CK (STM32_PLLCLKIN / STM32_PLL3_DIVM_VALUE) +#else +#error "invalid STM32_PLL3_DIVM_VALUE value specified" +#endif + +/* + * PLL3 input frequency range check. + */ +#if (STM32_PLL3_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL3_REF_CK > STM32_PLLIN_MAX) +#error "STM32_PLL3_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)" +#endif + +/** + * @brief PLL3 input range selector. + */ +#if (STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_0 +#elif STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD2 +#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_1 +#elif STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD3 +#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_2 +#else +#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_3 +#endif + +/** + * @brief PLL1 DIVN field. + */ +#if ((STM32_PLL1_DIVN_VALUE >= 4) && (STM32_PLL1_DIVN_VALUE <= 512)) || \ + defined(__DOXYGEN__) +#define STM32_PLL1_DIVN ((STM32_PLL1_DIVN_VALUE - 1U) << 0U) +#else +#error "invalid STM32_PLL1_DIVN_VALUE value specified" +#endif + +/** + * @brief PLL2 DIVN field. + */ +#if ((STM32_PLL2_DIVN_VALUE >= 4) && (STM32_PLL2_DIVN_VALUE <= 512)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2_DIVN ((STM32_PLL2_DIVN_VALUE - 1U) << 0U) +#else +#error "invalid STM32_PLL2_DIVN_VALUE value specified" +#endif + +/** + * @brief PLL3 DIVN field. + */ +#if ((STM32_PLL3_DIVN_VALUE >= 4) && (STM32_PLL3_DIVN_VALUE <= 512)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3_DIVN ((STM32_PLL3_DIVN_VALUE - 1U) << 0U) +#else +#error "invalid STM32_PLL3_DIVN_VALUE value specified" +#endif + +/** + * @brief PLL1 FRACN field. + */ +#if ((STM32_PLL1_FRACN_VALUE >= 0) && (STM32_PLL1_FRACN_VALUE <= 8191)) || \ + defined(__DOXYGEN__) +#define STM32_PLL1_FRACN (STM32_PLL1_FRACN_VALUE << 3U) +#else +#error "invalid STM32_PLL1_FRACN_VALUE value specified" +#endif + +/** + * @brief PLL2 FRACN field. + */ +#if ((STM32_PLL2_FRACN_VALUE >= 0) && (STM32_PLL2_FRACN_VALUE <= 8191)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2_FRACN (STM32_PLL2_FRACN_VALUE << 3U) +#else +#error "invalid STM32_PLL2_FRACN_VALUE value specified" +#endif + +/** + * @brief PLL3 FRACN field. + */ +#if ((STM32_PLL3_FRACN_VALUE >= 0) && (STM32_PLL3_FRACN_VALUE <= 8191)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3_FRACN (STM32_PLL3_FRACN_VALUE << 3U) +#else +#error "invalid STM32_PLL3_FRACN_VALUE value specified" +#endif + +/** + * @brief PLL1 DIVP field. + */ +#if ((STM32_PLL1_DIVP_VALUE >= 2) && (STM32_PLL1_DIVP_VALUE <= 128) && \ + ((STM32_PLL1_DIVP_VALUE & 1U) == 0U)) || \ + defined(__DOXYGEN__) +#define STM32_PLL1_DIVP ((STM32_PLL1_DIVP_VALUE - 1U) << 9U) +#else +#error "invalid STM32_PLL1_DIVP_VALUE value specified" +#endif + +/** + * @brief PLL2 DIVP field. + */ +#if ((STM32_PLL2_DIVP_VALUE >= 2) && (STM32_PLL2_DIVP_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2_DIVP ((STM32_PLL2_DIVP_VALUE - 1U) << 9U) +#else +#error "invalid STM32_PLL2_DIVP_VALUE value specified" +#endif + +/** + * @brief PLL3 DIVP field. + */ +#if ((STM32_PLL3_DIVP_VALUE >= 2) && (STM32_PLL3_DIVP_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3_DIVP ((STM32_PLL3_DIVP_VALUE - 1U) << 9U) +#else +#error "invalid STM32_PLL3_DIVP_VALUE value specified" +#endif + +/** + * @brief PLL1 DIVQ field. + */ +#if ((STM32_PLL1_DIVQ_VALUE >= 1) && (STM32_PLL1_DIVQ_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL1_DIVQ ((STM32_PLL1_DIVQ_VALUE - 1U) << 16U) +#else +#error "invalid STM32_PLL1_DIVQ_VALUE value specified" +#endif + +/** + * @brief PLL2 DIVQ field. + */ +#if ((STM32_PLL2_DIVQ_VALUE >= 1) && (STM32_PLL2_DIVQ_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2_DIVQ ((STM32_PLL2_DIVQ_VALUE - 1U) << 16U) +#else +#error "invalid STM32_PLL2_DIVQ_VALUE value specified" +#endif + +/** + * @brief PLL3 DIVQ field. + */ +#if ((STM32_PLL3_DIVQ_VALUE >= 1) && (STM32_PLL3_DIVQ_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3_DIVQ ((STM32_PLL3_DIVQ_VALUE - 1U) << 16U) +#else +#error "invalid STM32_PLL3_DIVQ_VALUE value specified" +#endif + +/** + * @brief PLL1 DIVR field. + */ +#if ((STM32_PLL1_DIVR_VALUE >= 1) && (STM32_PLL1_DIVR_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL1_DIVR ((STM32_PLL1_DIVR_VALUE - 1U) << 24U) +#else +#error "invalid STM32_PLL1_DIVR_VALUE value specified" +#endif + +/** + * @brief PLL2 DIVR field. + */ +#if ((STM32_PLL2_DIVR_VALUE >= 1) && (STM32_PLL2_DIVR_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL2_DIVR ((STM32_PLL2_DIVR_VALUE - 1U) << 24U) +#else +#error "invalid STM32_PLL2_DIVR_VALUE value specified" +#endif + +/** + * @brief PLL3 DIVR field. + */ +#if ((STM32_PLL3_DIVR_VALUE >= 1) && (STM32_PLL3_DIVR_VALUE <= 128)) || \ + defined(__DOXYGEN__) +#define STM32_PLL3_DIVR ((STM32_PLL3_DIVR_VALUE - 1U) << 24U) +#else +#error "invalid STM32_PLL3_DIVR_VALUE value specified" +#endif + +/** + * @brief PLL1 VCO frequency. + */ +#define STM32_PLL1_VCO_CK (STM32_PLL1_REF_CK * STM32_PLL1_DIVN_VALUE) + +/* + * PLL1 VCO frequency range check. + */ +#if (STM32_PLL1_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL1_VCO_CK > STM32_PLLVCO_MAX) +#error "STM32_PLL1_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)" +#endif + +/* + * PLL1 VCO mode. + */ +#if (STM32_PLL1_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_PLL1VCOSEL 0U +#else +#define STM32_PLLCFGR_PLL1VCOSEL RCC_PLLCFGR_PLL1VCOSEL +#endif + +/** + * @brief PLL2 VCO frequency. + */ +#define STM32_PLL2_VCO_CK (STM32_PLL2_REF_CK * STM32_PLL2_DIVN_VALUE) + +/* + * PLL2 VCO frequency range check. + */ +#if (STM32_PLL2_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL2_VCO_CK > STM32_PLLVCO_MAX) +#error "STM32_PLL2_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)" +#endif + +/* + * PLL2 VCO mode. + */ +#if (STM32_PLL2_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_PLL2VCOSEL 0U +#else +#define STM32_PLLCFGR_PLL2VCOSEL RCC_PLLCFGR_PLL2VCOSEL +#endif + +/** + * @brief PLL3 VCO frequency. + */ +#define STM32_PLL3_VCO_CK (STM32_PLL3_REF_CK * STM32_PLL3_DIVN_VALUE) + +/* + * PLL3 VCO frequency range check. + */ +#if (STM32_PLL3_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL3_VCO_CK > STM32_PLLVCO_MAX) +#error "STM32_PLL3_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)" +#endif + +/* + * PLL3 VCO mode. + */ +#if (STM32_PLL3_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_PLLCFGR_PLL3VCOSEL 0U +#else +#define STM32_PLLCFGR_PLL3VCOSEL RCC_PLLCFGR_PLL3VCOSEL +#endif + +#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_P_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL1 P output clock frequency. + */ +#define STM32_PLL1_P_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVP_VALUE) + +/* + * PLL1 P output frequency range check. + */ +#if (STM32_PLL1_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_P_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL1_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL1_P_CK 0U +#endif + +#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_P_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL2 P output clock frequency. + */ +#define STM32_PLL2_P_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVP_VALUE) + +/* + * PLL2 P output frequency range check. + */ +#if (STM32_PLL2_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_P_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL2_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL2_P_CK 0U +#endif + +#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_P_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL3 P output clock frequency. + */ +#define STM32_PLL3_P_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVP_VALUE) + +/* + * PLL3 P output frequency range check. + */ +#if (STM32_PLL3_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_P_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL3_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL3_P_CK 0U +#endif + +#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_Q_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL1 Q output clock frequency. + */ +#define STM32_PLL1_Q_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVQ_VALUE) + +/* + * PLL1 Q output frequency range check. + */ +#if (STM32_PLL1_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_Q_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL1_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL1_Q_CK 0U +#endif + +#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_Q_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL2 Q output clock frequency. + */ +#define STM32_PLL2_Q_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVQ_VALUE) + +/* + * PLL2 Q output frequency range check. + */ +#if (STM32_PLL2_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_Q_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL2_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL2_Q_CK 0U +#endif + +#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_Q_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL3 Q output clock frequency. + */ +#define STM32_PLL3_Q_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVQ_VALUE) + +/* + * PLL3 Q output frequency range check. + */ +#if (STM32_PLL3_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_Q_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL3_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL3_Q_CK 0U +#endif + +#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_R_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL1 R output clock frequency. + */ +#define STM32_PLL1_R_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVR_VALUE) + +/* + * PLL1 R output frequency range check. + */ +#if (STM32_PLL1_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_R_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL1_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL1_R_CK 0U +#endif + +#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_R_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL2 R output clock frequency. + */ +#define STM32_PLL2_R_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVR_VALUE) + +/* + * PLL2 R output frequency range check. + */ +#if (STM32_PLL2_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_R_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL2_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL2_R_CK 0U +#endif + +#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_R_ENABLED == TRUE)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL3 R output clock frequency. + */ +#define STM32_PLL3_R_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVR_VALUE) + +/* + * PLL3 R output frequency range check. + */ +#if (STM32_PLL3_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_R_CK > STM32_PLLOUT_MAX) +#error "STM32_PLL3_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)" +#endif +#else +#define STM32_PLL3_R_CK 0U +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_HSI_CK) || defined(__DOXYGEN__) +#define STM32_SYS_CK STM32_HSI_CK + +#elif (STM32_SW == STM32_SW_CSI_CK) +#define STM32_SYS_CK STM32_CSI_CK + +#elif (STM32_SW == STM32_SW_HSE_CK) +#define STM32_SYS_CK STM32_HSE_CK + +#elif (STM32_SW == STM32_SW_PLL1_P_CK) +#define STM32_SYS_CK STM32_PLL1_P_CK + +#else +#error "invalid STM32_SW value specified" +#endif + +/* + * Check on the system clock. + */ +#if STM32_SYS_CK > STM32_SYSCLK_MAX +#error "STM32_SYS_CK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/* + * ODEN setting based on clock frequency. + */ +#if STM32_SYS_CK > STM32_SYSCLK_MAX_NOBOOST +#define STM32_ODEN STM32_ODEN_ENABLED +#else +#define STM32_ODEN STM32_ODEN_DISABLED +#endif + +/** + * @brief Peripherals clock source. + */ +#if (STM32_CKPERSEL == STM32_CKPERSEL_HSI_CK) || defined(__DOXYGEN__) +#define STM32_PER_CK STM32_HSI_CK + +#elif (STM32_CKPERSEL == STM32_CKPERSEL_CSI_CK) +#define STM32_PER_CK STM32_CSI_CK + +#elif (STM32_CKPERSEL == STM32_CKPERSEL_HSE_CK) +#define STM32_PER_CK STM32_HSE_CK + +#else +#error "invalid STM32_CKPERSEL value specified" +#endif + +/* + * Check on the peripherals clock. + */ +#if STM32_PER_CK > STM32_HCLK_MAX +#error "STM32_PER_CK above maximum rated frequency (STM32_HCLK_MAX)" +#endif + +/** + * @brief MCO1 divider clock. + */ +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI_CK) || defined(__DOXYGEN__) +#define STM32_MCO1DIVCLK STM32_HSI_CK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE_CK +#define STM32_MCO1DIVCLK STM32_LSE_CK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE_CK +#define STM32_MCO1DIVCLK STM32_HSE_CK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL1_Q_CK +#define STM32_MCO1DIVCLK STM32_PLL1_P_CK + +#elif STM32_MCO1SEL == STM32_MCO1SEL_HSI48_CK +#define STM32_MCO1DIVCLK STM32_HSI48_CK + +#else +#error "invalid STM32_MCO1SEL value specified" +#endif + +/** + * @brief MCO1 output pin clock. + */ +#if (STM32_MCO1PRE_VALUE < 1) || (STM32_MCO1PRE_VALUE > 15) +#error "STM32_MCO1PRE_VALUE outside acceptable range (1..15)" +#endif + +/** + * @brief MCO2 divider clock. + */ +#if (STM32_MCO2SEL == STM32_MCO2SEL_SYS_CK) || defined(__DOXYGEN__) +#define STM32_MCO2DIVCLK STM32_SYS_CK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL1_P_CK +#define STM32_MCO2DIVCLK STM32_PLL2_P_CK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_HSE_CK +#define STM32_MCO2DIVCLK STM32_HSE_CK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL2_P_CK +#define STM32_MCO2DIVCLK STM32_PLL2_P_CK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_CSI_CK +#define STM32_MCO2DIVCLK STM32_CSI_CK + +#elif STM32_MCO2SEL == STM32_MCO2SEL_LSI_CK +#define STM32_MCO2DIVCLK STM32_LSI_CK + +#else +#error "invalid STM32_MCO2SEL value specified" +#endif + +/** + * @brief MCO2 output pin clock. + */ +#if (STM32_MCO2PRE_VALUE < 1) || (STM32_MCO2PRE_VALUE > 15) +#error "STM32_MCO2PRE_VALUE outside acceptable range (1..15)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLK) || defined(__DOXYGEN__) +#define STM32_RTC_CK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE_CK +#define STM32_RTC_CK STM32_LSE_CK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI_CK +#define STM32_RTC_CK STM32_LSI_CK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSE_1M_CK +#define STM32_RTC_CK STM32_HSE_1M_CK + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/* + * Check on the RTC clock. + */ +#if STM32_RTC_CK > 1000000 +#error "STM32_RTC_CK above maximum rated frequency (1000000)" +#endif + +/** + * @brief D1CPRE clock. + */ +#if (STM32_D1CPRE == STM32_D1CPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 1U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV2 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 2U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV4 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 4U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV8 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 8U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV16 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 16U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV64 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 64U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV128 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 128U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV256 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 256U) +#elif STM32_D1CPRE == STM32_D1CPRE_DIV512 +#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 512U) +#else +#error "invalid STM32_D1CPRE value specified" +#endif + +/** + * @brief HCLK clock. + */ +#if (STM32_D1HPRE == STM32_D1HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 1U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV2 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 2U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV4 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 4U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV8 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 8U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV16 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 16U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV64 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 64U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV128 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 128U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV256 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 256U) +#elif STM32_D1HPRE == STM32_D1HPRE_DIV512 +#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 512U) +#else +#error "invalid STM32_D1HPRE value specified" +#endif + +/** + * @brief Core clock. + */ +#define STM32_CORE1_CK STM32_SYS_D1CPRE_CK + +/** + * @brief Core clock. + */ +#define STM32_CORE2_CK STM32_HCLK + +#if (STM32_TARGET_CORE == 1) || defined(__DOXYGEN__) + +#if STM32_HAS_M7 != TRUE +#error "Cortex-M7 not present in this device" +#endif +#define STM32_CORE_CK STM32_CORE1_CK + +#elif STM32_TARGET_CORE == 2 + +#if STM32_HAS_M4 != TRUE +#error "Cortex-M4 not present in this device" +#endif +#define STM32_CORE_CK STM32_CORE2_CK + +#else +#error "invalid STM32_TARGET_CORE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_HCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_HCLK_MAX)" +#endif + +/** + * @brief D1 PCLK3 clock. + */ +#if (STM32_D1PPRE3 == STM32_D1PPRE3_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK3 (STM32_HCLK / 1U) +#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV2 +#define STM32_PCLK3 (STM32_HCLK / 2U) +#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV4 +#define STM32_PCLK3 (STM32_HCLK / 4U) +#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV8 +#define STM32_PCLK3 (STM32_HCLK / 8U) +#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV16 +#define STM32_PCLK3 (STM32_HCLK / 16U) +#else +#error "invalid STM32_D1PPRE3 value specified" +#endif + +/* + * D1 PCLK3 frequency check. + */ +#if STM32_PCLK3 > STM32_PCLK3_MAX +#error "STM32_PCLK3 exceeding maximum frequency (STM32_PCLK3_MAX)" +#endif + +/** + * @brief D2 PCLK1 clock. + */ +#if (STM32_D2PPRE1 == STM32_D2PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1U) +#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2U) +#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4U) +#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8U) +#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16U) +#else +#error "invalid STM32_D2PPRE1 value specified" +#endif + +/* + * D2 PCLK1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief D2 PCLK2 clock. + */ +#if (STM32_D2PPRE2 == STM32_D2PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1U) +#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2U) +#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4U) +#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8U) +#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16U) +#else +#error "invalid STM32_D2PPRE2 value specified" +#endif + +/* + * D2 PCLK2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief D3 PCLK4 clock. + */ +#if (STM32_D3PPRE4 == STM32_D3PPRE4_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK4 (STM32_HCLK / 1U) +#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV2 +#define STM32_PCLK4 (STM32_HCLK / 2U) +#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV4 +#define STM32_PCLK4 (STM32_HCLK / 4U) +#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV8 +#define STM32_PCLK4 (STM32_HCLK / 8U) +#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV16 +#define STM32_PCLK4 (STM32_HCLK / 16U) +#else +#error "invalid STM32_D3PPRE4 value specified" +#endif + +/* + * D3 PCLK4 frequency check. + */ +#if STM32_PCLK4 > STM32_PCLK4_MAX +#error "STM32_PCLK4 exceeding maximum frequency (STM32_PCLK4_MAX)" +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000000 + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS 0x00000001 + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS 0x00000002 + +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS 0x00000003 + +#elif STM32_HCLK <= STM32_4WS_THRESHOLD +#define STM32_FLASHBITS 0x00000004 + +#else +#define STM32_FLASHBITS 0x00000007 +#endif + +#if (STM32_D2PPRE1 == STM32_D2PPRE1_DIV1) || defined(__DOXYGEN__) +/** + * @brief Clock of timers connected to APB1 + */ +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#if (STM32_TIMPRE_ENABLE == FALSE) || (STM32_D2PPRE1 == STM32_D2PPRE1_DIV2) +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 4) +#endif +#endif + +#if (STM32_D2PPRE2 == STM32_D2PPRE2_DIV1) || defined(__DOXYGEN__) +/** + * @brief Clock of timers connected to APB2. + */ +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#if (STM32_TIMPRE_ENABLE == FALSE) || (STM32_D2PPRE2 == STM32_D2PPRE2_DIV2) +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 4) +#endif +#endif + +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) +/** + * @brief LPTIM1 clock. + */ +#define STM32_LPTIM1CLK STM32_PCLK1 + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PLL2_P_CK +#define STM32_LPTIM1CLK STM32_PLL2_P_CK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PLL3_R_CK +#define STM32_LPTIM1CLK STM32_PLL3_R_CK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE_CK +#define STM32_LPTIM1CLK STM32_LSE_CK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI_CK +#define STM32_LPTIM1CLK STM32_LSI_CK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PER_CK +#define STM32_LPTIM1CLK STM32_PER_CK +#else +#error "invalid source selected for STM32_LPTIM1SEL clock" +#endif + +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK4) || defined(__DOXYGEN__) +/** + * @brief LPTIM2 clock. + */ +#define STM32_LPTIM2CLK STM32_PCLK4 + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PLL2_P_CK +#define STM32_LPTIM2CLK STM32_PLL2_P_CK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PLL3_P_CK +#define STM32_LPTIM2CLK STM32_PLL3_P_CK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE_CK +#define STM32_LPTIM2CLK STM32_LSE_CK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI_CK +#define STM32_LPTIM2CLK STM32_LSI_CK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PER_CK +#define STM32_LPTIM2CLK STM32_PER_CK +#else +#error "invalid source selected for STM32_LPTIM2SEL clock" +#endif + +#if (STM32_LPTIM345SEL == STM32_LPTIM345SEL_PCLK4) || defined(__DOXYGEN__) +/** + * @brief LPTIM3 clock. + */ +#define STM32_LPTIM3CLK STM32_PCLK4 + +/** + * @brief LPTIM4 clock. + */ +#define STM32_LPTIM4CLK STM32_PCLK4 + +/** + * @brief LPTIM5 clock. + */ +#define STM32_LPTIM5CLK STM32_PCLK4 + +#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PLL2_P_CK +#define STM32_LPTIM3CLK STM32_PLL2_P_CK +#define STM32_LPTIM4CLK STM32_PLL2_P_CK +#define STM32_LPTIM5CLK STM32_PLL2_P_CK +#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PLL3_P_CK +#define STM32_LPTIM3CLK STM32_PLL3_P_CK +#define STM32_LPTIM4CLK STM32_PLL3_P_CK +#define STM32_LPTIM5CLK STM32_PLL3_P_CK +#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_LSE_CK +#define STM32_LPTIM3CLK STM32_LSE_CK +#define STM32_LPTIM4CLK STM32_LSE_CK +#define STM32_LPTIM5CLK STM32_LSE_CK +#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_LSI_CK +#define STM32_LPTIM3CLK STM32_LSI_CK +#define STM32_LPTIM4CLK STM32_LSI_CK +#define STM32_LPTIM5CLK STM32_LSI_CK +#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PER_CK +#define STM32_LPTIM3CLK STM32_PER_CK +#define STM32_LPTIM4CLK STM32_PER_CK +#define STM32_LPTIM5CLK STM32_PER_CK +#else +#error "invalid source selected for STM32_LPTIM345SEL clock" +#endif + +#if (STM32_USART16SEL == STM32_USART16SEL_PCLK2) || defined(__DOXYGEN__) +/** + * @brief USART1 clock. + */ +#define STM32_USART1CLK STM32_PCLK2 + +/** + * @brief USART6 clock. + */ +#define STM32_USART6CLK STM32_PCLK2 + +#elif STM32_USART16SEL == STM32_USART16SEL_PLL2_Q_CK +#define STM32_USART1CLK STM32_PLL2_Q_CK +#define STM32_USART6CLK STM32_PLL2_Q_CK +#elif STM32_USART16SEL == STM32_USART16SEL_PLL3_Q_CK +#define STM32_USART1CLK STM32_PLL3_Q_CK +#define STM32_USART6CLK STM32_PLL3_Q_CK +#elif STM32_USART16SEL == STM32_USART16SEL_HSI_KER_CK +#define STM32_USART1CLK STM32_HSI_CK +#define STM32_USART6CLK STM32_HSI_CK +#elif STM32_USART16SEL == STM32_USART16SEL_CSI_KER_CK +#define STM32_USART1CLK STM32_CSI_CK +#define STM32_USART6CLK STM32_CSI_CK +#elif STM32_USART16SEL == STM32_USART16SEL_LSE_CK +#define STM32_USART1CLK STM32_LSE_CK +#define STM32_USART6CLK STM32_LSE_CK +#else +#error "invalid source selected for STM32_USART16SEL clock" +#endif + +#if (STM32_USART234578SEL == STM32_USART234578SEL_PCLK1) || defined(__DOXYGEN__) +/** + * @brief USART2 clock. + */ +#define STM32_USART2CLK STM32_PCLK1 + +/** + * @brief USART3 clock. + */ +#define STM32_USART3CLK STM32_PCLK1 + +/** + * @brief USART4 clock. + */ +#define STM32_UART4CLK STM32_PCLK1 + +/** + * @brief USART5 clock. + */ +#define STM32_UART5CLK STM32_PCLK1 + +/** + * @brief USART7 clock. + */ +#define STM32_UART7CLK STM32_PCLK1 + +/** + * @brief USART8 clock. + */ +#define STM32_UART8CLK STM32_PCLK1 + +#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL2_Q_CK +#define STM32_USART2CLK STM32_PLL2_Q_CK +#define STM32_USART3CLK STM32_PLL2_Q_CK +#define STM32_UART4CLK STM32_PLL2_Q_CK +#define STM32_UART5CLK STM32_PLL2_Q_CK +#define STM32_UART7CLK STM32_PLL2_Q_CK +#define STM32_UART8CLK STM32_PLL2_Q_CK +#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL3_Q_CK +#define STM32_USART2CLK STM32_PLL3_Q_CK +#define STM32_USART3CLK STM32_PLL3_Q_CK +#define STM32_UART4CLK STM32_PLL3_Q_CK +#define STM32_UART5CLK STM32_PLL3_Q_CK +#define STM32_UART7CLK STM32_PLL3_Q_CK +#define STM32_UART8CLK STM32_PLL3_Q_CK +#elif STM32_USART234578SEL == STM32_USART234578SEL_HSI_KER_CK +#define STM32_USART2CLK STM32_HSI_CK +#define STM32_USART3CLK STM32_HSI_CK +#define STM32_UART4CLK STM32_HSI_CK +#define STM32_UART5CLK STM32_HSI_CK +#define STM32_UART7CLK STM32_HSI_CK +#define STM32_UART8CLK STM32_HSI_CK +#elif STM32_USART234578SEL == STM32_USART234578SEL_CSI_KER_CK +#define STM32_USART2CLK STM32_CSI_CK +#define STM32_USART3CLK STM32_CSI_CK +#define STM32_UART4CLK STM32_CSI_CK +#define STM32_UART5CLK STM32_CSI_CK +#define STM32_UART7CLK STM32_CSI_CK +#define STM32_UART8CLK STM32_CSI_CK +#elif STM32_USART234578SEL == STM32_USART234578SEL_LSE_CK +#define STM32_USART2CLK STM32_LSE_CK +#define STM32_USART3CLK STM32_LSE_CK +#define STM32_UART4CLK STM32_LSE_CK +#define STM32_UART6CLK STM32_LSE_CK +#define STM32_UART7CLK STM32_LSE_CK +#define STM32_UART8CLK STM32_LSE_CK +#else +#error "invalid source selected for STM32_USART234578SEL clock" +#endif + +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK4) || defined(__DOXYGEN__) +/** + * @brief LPUART1 clock. + */ +#define STM32_LPUART1CLK STM32_PCLK4 + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_PLL2_Q_CK +#define STM32_LPUART1CLK STM32_PLL2_Q_CK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_PLL3_Q_CK +#define STM32_LPUART1CLK STM32_PLL3_Q_CK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI_KER_CK +#define STM32_LPUART1CLK STM32_HSI_CK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_CSI_KER_CK +#define STM32_LPUART1CLK STM32_CSI_CK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE_CK +#define STM32_LPUART1CLK STM32_LSE_CK +#else +#error "invalid source selected for STM32_LPUART1SEL clock" +#endif + +#if (STM32_SPI123SEL == STM32_SPI123SEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SPI1 clock. + */ +#define STM32_SPI1CLK STM32_PLL1_Q_CK + +/** + * @brief SPI2 clock. + */ +#define STM32_SPI2CLK STM32_PLL1_Q_CK + +/** + * @brief SPI3 clock. + */ +#define STM32_SPI3CLK STM32_PLL1_Q_CK +#elif STM32_SPI123SEL == STM32_SPI123SEL_PLL2_P_CK +#define STM32_SPI1CLK STM32_PLL2_P_CK +#define STM32_SPI2CLK STM32_PLL2_P_CK +#define STM32_SPI3CLK STM32_PLL2_P_CK +#elif STM32_SPI123SEL == STM32_SPI123SEL_PLL3_P_CK +#define STM32_SPI1CLK STM32_PLL3_P_CK +#define STM32_SPI2CLK STM32_PLL3_P_CK +#define STM32_SPI3CLK STM32_PLL3_P_CK +#elif STM32_SPI123SEL == STM32_SPI123SEL_I2S_CKIN +#define STM32_SPI1CLK 0 /* Unknown, would require a board value */ +#define STM32_SPI2CLK 0 /* Unknown, would require a board value */ +#define STM32_SPI3CLK 0 /* Unknown, would require a board value */ +#elif STM32_SPI123SEL == STM32_SPI123SEL_PER_CK +#define STM32_SPI1CLK STM32_PER_CK +#define STM32_SPI2CLK STM32_PER_CK +#define STM32_SPI3CLK STM32_PER_CK +#else +#error "invalid source selected for STM32_SPI123SEL clock" +#endif + +#if (STM32_SPI45SEL == STM32_SPI45SEL_PCLK2) || defined(__DOXYGEN__) +/** + * @brief SPI4 clock. + */ +#define STM32_SPI4CLK STM32_PCLK2 + +/** + * @brief SPI5 clock. + */ +#define STM32_SPI5CLK STM32_PCLK2 + +#elif STM32_SPI45SEL == STM32_SPI45SEL_PLL2_Q_CK +#define STM32_SPI4CLK STM32_PLL2_Q_CK +#define STM32_SPI5CLK STM32_PLL2_Q_CK +#elif STM32_SPI45SEL == STM32_SPI45SEL_PLL3_Q_CK +#define STM32_SPI4CLK STM32_PLL3_Q_CK +#define STM32_SPI5CLK STM32_PLL3_Q_CK +#elif STM32_SPI45SEL == STM32_SPI45SEL_HSI_KER_CK +#define STM32_SPI4CLK STM32_HSI_CK +#define STM32_SPI5CLK STM32_HSI_CK +#elif STM32_SPI45SEL == STM32_SPI45SEL_CSI_KER_CK +#define STM32_SPI4CLK STM32_CSI_CK +#define STM32_SPI5CLK STM32_CSI_CK +#elif STM32_SPI45SEL == STM32_SPI45SEL_HSE_CK +#define STM32_SPI4CLK STM32_HSE_CK +#define STM32_SPI5CLK STM32_HSE_CK +#else +#error "invalid source selected for STM32_SPI45SEL clock" +#endif + +#if (STM32_SPI6SEL == STM32_SPI6SEL_PCLK4) || defined(__DOXYGEN__) +/** + * @brief SPI6 clock. + */ +#define STM32_SPI6CLK STM32_PCLK4 + +#elif STM32_SPI6SEL == STM32_SPI6SEL_PLL2_Q_CK +#define STM32_SPI6CLK STM32_PLL2_Q_CK +#elif STM32_SPI6SEL == STM32_SPI6SEL_PLL3_Q_CK +#define STM32_SPI6CLK STM32_PLL3_Q_CK +#elif STM32_SPI6SEL == STM32_SPI6SEL_HSI_KER_CK +#define STM32_SPI6CLK STM32_HSI_CK +#elif STM32_SPI6SEL == STM32_SPI6SEL_CSI_KER_CK +#define STM32_SPI6CLK STM32_CSI_CK +#elif STM32_SPI6SEL == STM32_SPI6SEL_HSE_CK +#define STM32_SPI6CLK STM32_HSE_CK +#else +#error "invalid source selected for STM32_SPI6SEL clock" +#endif + +#if (STM32_I2C123SEL == STM32_I2C123SEL_PCLK1) || defined(__DOXYGEN__) +/** + * @brief I2C1 clock. + */ +#define STM32_I2C1CLK STM32_PCLK1 + +/** + * @brief I2C2 clock. + */ +#define STM32_I2C2CLK STM32_PCLK1 + +/** + * @brief I2C2 clock. + */ +#define STM32_I2C2CLK STM32_PCLK1 + +#elif STM32_I2C123SEL == STM32_I2C123SEL_PLL3_R_CK +#define STM32_I2C1CLK STM32_PLL3_R_CK +#define STM32_I2C2CLK STM32_PLL3_R_CK +#define STM32_I2C2CLK STM32_PLL3_R_CK + +#elif STM32_I2C123SEL == STM32_I2C123SEL_HSI_KER_CK +#define STM32_I2C1CLK STM32_HSI_CK +#define STM32_I2C2CLK STM32_HSI_CK +#define STM32_I2C2CLK STM32_HSI_CK + +#elif STM32_I2C123SEL == STM32_I2C123SEL_CSI_KER_CK +#define STM32_I2C1CLK STM32_CSI_CK +#define STM32_I2C2CLK STM32_CSI_CK +#define STM32_I2C2CLK STM32_CSI_CK +#else +#error "invalid source selected for STM32_I2C123SEL clock" +#endif + +#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK4) || defined(__DOXYGEN__) +/** + * @brief I2C1 clock. + */ +#define STM32_I2C4CLK STM32_PCLK4 + +#elif STM32_I2C4SEL == STM32_I2C4SEL_PLL3_R_CK +#define STM32_I2C4CLK STM32_PLL3_R_CK +#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI_KER_CK +#define STM32_I2C4CLK STM32_HSI_CK +#elif STM32_I2C4SEL == STM32_I2C4SEL_CSI_KER_CK +#define STM32_I2C4CLK STM32_CSI_CK +#else +#error "invalid source selected for STM32_I2C4SEL clock" +#endif + +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SAI1 clock. + */ +#define STM32_SAI1CLK STM32_PLL1_Q_CK + +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL2_P_CK +#define STM32_SAI1CLK STM32_PLL2_P_CK +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL3_P_CK +#define STM32_SAI1CLK STM32_PLL3_P_CK +#elif STM32_SAI1SEL == STM32_SAI1SEL_I2S_CKIN +#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ +#elif STM32_SAI1SEL == STM32_SAI1SEL_PER_CK +#define STM32_SAI1CLK STM32_PER_CK +#else +#error "invalid source selected for STM32_SAI1SEL clock" +#endif + +#if (STM32_SAI23SEL == STM32_SAI23SEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SAI2 clock. + */ +#define STM32_SAI2CLK STM32_PLL1_Q_CK + +/** + * @brief SAI3 clock. + */ +#define STM32_SAI3CLK STM32_PLL1_Q_CK + +#elif STM32_SAI23SEL == STM32_SAI23SEL_PLL2_P_CK +#define STM32_SAI2CLK STM32_PLL2_P_CK +#define STM32_SAI3CLK STM32_PLL2_P_CK +#elif STM32_SAI23SEL == STM32_SAI23SEL_PLL3_P_CK +#define STM32_SAI2CLK STM32_PLL3_P_CK +#define STM32_SAI3CLK STM32_PLL3_P_CK +#elif STM32_SAI23SEL == STM32_SAI23SEL_I2S_CKIN +#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ +#define STM32_SAI3CLK 0 /* Unknown, would require a board value */ +#elif STM32_SAI23SEL == STM32_SAI23SEL_PER_CK +#define STM32_SAI2CLK STM32_PER_CK +#define STM32_SAI3CLK STM32_PER_CK +#else +#error "invalid source selected for STM32_SAI23SEL clock" +#endif + +#if (STM32_SAI4ASEL == STM32_SAI4ASEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SAI4A clock. + */ +#define STM32_SAI4ACLK STM32_PLL1_Q_CK + +#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PLL2_P_CK +#define STM32_SAI4ACLK STM32_PLL2_P_CK +#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PLL3_P_CK +#define STM32_SAI4ACLK STM32_PLL3_P_CK +#elif STM32_SAI4ASEL == STM32_SAI4ASEL_I2S_CKIN +#define STM32_SAI4ACLK 0 /* Unknown, would require a board value */ +#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PER_CK +#define STM32_SAI4ACLK STM32_PER_CK +#else +#error "invalid source selected for STM32_SAI4ASEL clock" +#endif + +#if (STM32_SAI4BSEL == STM32_SAI4BSEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SAI4B clock. + */ +#define STM32_SAI4BCLK STM32_PLL1_Q_CK + +#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PLL2_P_CK +#define STM32_SAI4BCLK STM32_PLL2_P_CK +#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PLL3_P_CK +#define STM32_SAI4BCLK STM32_PLL3_P_CK +#elif STM32_SAI4BSEL == STM32_SAI4BSEL_I2S_CKIN +#define STM32_SAI4BCLK 0 /* Unknown, would require a board value */ +#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PER_CK +#define STM32_SAI4BCLK STM32_PER_CK +#else +#error "invalid source selected for STM32_SAI4BSEL clock" +#endif + +#if (STM32_USBSEL == STM32_USBSEL_DISABLE) || defined(__DOXYGEN__) +/** + * @brief USB clock. + */ +#define STM32_USBCLK 0 + +#elif STM32_USBSEL == STM32_USBSEL_PLL1_Q_CK +#define STM32_USBCLK STM32_PLL1_Q_CK +#elif STM32_USBSEL == STM32_USBSEL_PLL3_Q_CK +#define STM32_USBCLK STM32_PLL3_Q_CK +#elif STM32_USBSEL == STM32_USBSEL_HSI48_CK +#define STM32_USBCLK STM32_HSI48_CK +#else +#error "invalid source selected for STM32_USBSEL clock" +#endif + +#if (STM32_SDMMCSEL == STM32_SDMMCSEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SDMMC1 frequency. + */ +#define STM32_SDMMC1CLK STM32_PLL1_Q_CK + +/** + * @brief SDMMC2 frequency. + */ +#define STM32_SDMMC2CLK STM32_PLL1_Q_CK + +#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLL2_R_CK +#define STM32_SDMMC1CLK STM32_PLL2_R_CK +#define STM32_SDMMC2CLK STM32_PLL2_R_CK +#else +#error "invalid source selected for STM32_SDMMCxSEL clock" +#endif + +#if (STM32_QSPISEL == STM32_QSPISEL_HCLK) || defined(__DOXYGEN__) +/** + * @brief QSPI frequency. + */ +#define STM32_QSPICLK STM32_HCLK + +#elif STM32_QSPISEL == STM32_QSPISEL_PLL1_Q_CK +#define STM32_QSPICLK STM32_PLL1_Q_CK +#elif STM32_QSPISEL == STM32_QSPISEL_PLL2_R_CK +#define STM32_QSPICLK STM32_PLL2_R_CK +#elif STM32_QSPISEL == STM32_QSPISEL_PER_CK +#define STM32_QSPICLK STM32_PER_CK +#else +#error "invalid source selected for STM32_QSPISEL clock" +#endif + +#if (STM32_FMCSEL == STM32_FMCSEL_HCLK) || defined(__DOXYGEN__) +/** + * @brief FMC frequency. + */ +#define STM32_FMCCLK STM32_HCLK + +#elif STM32_FMCSEL == STM32_FMCSEL_PLL1_Q_CK +#define STM32_FMCCLK STM32_PLL1_Q_CK +#elif STM32_FMCSEL == STM32_FMCSEL_PLL2_R_CK +#define STM32_FMCCLK STM32_PLL2_R_CK +#elif STM32_FMCSEL == STM32_FMCSEL_PER_CK +#define STM32_FMCCLK STM32_PER_CK +#else +#error "invalid source selected for STM32_FMCSEL clock" +#endif + +#if (STM32_SWPSEL == STM32_SWPSEL_PCLK1) || defined(__DOXYGEN__) +/** + * @brief SDMMC frequency. + */ +#define STM32_SWPCLK STM32_PCLK1 + +#elif STM32_SWPSEL == STM32_SWPSEL_HSI_KER_CK +#define STM32_SWPCLK STM32_HSI_CK +#else +#error "invalid source selected for STM32_SWPSEL clock" +#endif + +#if (STM32_FDCANSEL == STM32_FDCANSEL_HSE_CK) || defined(__DOXYGEN__) +/** + * @brief FDCAN frequency. + */ +#define STM32_FDCANCLK STM32_HSE_CK + +#elif STM32_FDCANSEL == STM32_FDCANSEL_PLL1_Q_CK +#define STM32_FDCANCLK STM32_PLL1_Q_CK +#elif STM32_FDCANSEL == STM32_FDCANSEL_PLL2_Q_CK +#define STM32_FDCANCLK STM32_PLL2_Q_CK +#else +#error "invalid source selected for STM32_FDCANSEL clock" +#endif + +#if (STM32_DFSDM1SEL == STM32_DFSDM1SEL_PCLK2) || defined(__DOXYGEN__) +/** + * @brief SDMMC frequency. + */ +#define STM32_DFSDM1CLK STM32_PCLK2 + +#elif STM32_DFSDM1SEL == STM32_DFSDM1SEL_SYS_CK +#define STM32_DFSDM1CLK STM32_SYS_CK +#else +#error "invalid source selected for STM32_DFSDM1SEL clock" +#endif + +#if (STM32_SPDIFSEL == STM32_SPDIFSEL_PLL1_Q_CK) || defined(__DOXYGEN__) +/** + * @brief SPDIF frequency. + */ +#define STM32_SPDIFCLK STM32_PLL1_Q_CK + +#elif STM32_SPDIFSEL == STM32_SPDIFSEL_PLL2_R_CK +#define STM32_SPDIFCLK STM32_PLL2_R_CK +#elif STM32_SPDIFSEL == STM32_SPDIFSEL_PLL3_R_CK +#define STM32_SPDIFCLK STM32_PLL3_R_CK +#elif STM32_SPDIFSEL == STM32_SPDIFSEL_HSI_KET_CLK +#define STM32_SPDIFCLK STM32_HSI_CK +#else +#error "invalid source selected for STM32_SPDIFSEL clock" +#endif + +#if (STM32_CECSEL == STM32_CECSEL_LSE_CK) || defined(__DOXYGEN__) +/** + * @brief CEC frequency. + */ +#define STM32_CECCLK STM32_LSE_CK + +#elif STM32_CECSEL == STM32_CECSEL_LSI_CK +#define STM32_CECCLK STM32_LSI_CK +#elif STM32_CECSEL == STM32_CECSEL_CSI_KER_CK +#define STM32_CECCLK STM32_CSI_CK +#elif STM32_CECSEL == STM32_CECSEL_DISABLE +#define STM32_CECCLK 0 +#else +#error "invalid source selected for STM32_CECSEL clock" +#endif + +#if (STM32_RNGSEL == STM32_RNGSEL_HSI48_CK) || defined(__DOXYGEN__) +/** + * @brief RNG frequency. + */ +#define STM32_RNGCLK STM32_HSI48_CK + +#elif STM32_RNGSEL == STM32_RNGSEL_PLL1_Q_CK +#define STM32_RNGCLK STM32_PLL1_Q_CK +#elif STM32_RNGSEL == STM32_RNGSEL_LSE_CK +#define STM32_RNGCLK STM32_LSE_CK +#elif STM32_RNGSEL == STM32_RNGSEL_LSI_CK +#define STM32_RNGCLK STM32_LSI_CK +#else +#error "invalid source selected for STM32_RNGSEL clock" +#endif + +#if (STM32_ADCSEL == STM32_ADCSEL_PLL2_P_CK) || defined(__DOXYGEN__) +/** + * @brief ADC frequency. + */ +#define STM32_ADCCLK STM32_PLL2_P_CK + +#elif STM32_ADCSEL == STM32_ADCSEL_PLL3_R_CK +#define STM32_ADCCLK STM32_PLL3_R_CK +#elif STM32_ADCSEL == STM32_ADCSEL_PER_CK +#define STM32_ADCCLK STM32_PER_CK +#elif STM32_ADCSEL == STM32_ADCSEL_DISABLE +#define STM32_ADCCLK 0 +#else +#error "invalid source selected for STM32_ADCSEL clock" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_mdma.h" +#include "stm32_dma.h" +#include "stm32_bdma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/platform.mk b/os/hal/ports/STM32/STM32H7xx/platform.mk index 830fd82da3..ae9c00572e 100644 --- a/os/hal/ports/STM32/STM32H7xx/platform.mk +++ b/os/hal/ports/STM32/STM32H7xx/platform.mk @@ -1,51 +1,51 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv2/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h b/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h index d870d956da..c93b688b91 100644 --- a/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h +++ b/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h @@ -1,206 +1,206 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32H7xx/stm32_dmamux.h - * @brief STM32H7xx DMAMUX handler header. - * - * @addtogroup STM32H7xx_DMAMUX - * @{ - */ - -#ifndef STM32_DMAMUX_H -#define STM32_DMAMUX_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name DMAMUX1 request sources - * @{ - */ -#define STM32_DMAMUX1_REQ_GEN0 1 -#define STM32_DMAMUX1_REQ_GEN1 2 -#define STM32_DMAMUX1_REQ_GEN2 3 -#define STM32_DMAMUX1_REQ_GEN3 4 -#define STM32_DMAMUX1_REQ_GEN4 5 -#define STM32_DMAMUX1_REQ_GEN5 6 -#define STM32_DMAMUX1_REQ_GEN6 7 -#define STM32_DMAMUX1_REQ_GEN7 8 -#define STM32_DMAMUX1_ADC1 9 -#define STM32_DMAMUX1_ADC2 10 -#define STM32_DMAMUX1_TIM1_CH1 11 -#define STM32_DMAMUX1_TIM1_CH2 12 -#define STM32_DMAMUX1_TIM1_CH3 13 -#define STM32_DMAMUX1_TIM1_CH4 14 -#define STM32_DMAMUX1_TIM1_UP 15 -#define STM32_DMAMUX1_TIM1_TRIG 16 -#define STM32_DMAMUX1_TIM1_COM 17 -#define STM32_DMAMUX1_TIM2_CH1 18 -#define STM32_DMAMUX1_TIM2_CH2 19 -#define STM32_DMAMUX1_TIM2_CH3 20 -#define STM32_DMAMUX1_TIM2_CH4 21 -#define STM32_DMAMUX1_TIM2_UP 22 -#define STM32_DMAMUX1_TIM3_CH1 23 -#define STM32_DMAMUX1_TIM3_CH2 24 -#define STM32_DMAMUX1_TIM3_CH3 25 -#define STM32_DMAMUX1_TIM3_CH4 26 -#define STM32_DMAMUX1_TIM3_UP 27 -#define STM32_DMAMUX1_TIM3_TRIG 28 -#define STM32_DMAMUX1_TIM4_CH1 29 -#define STM32_DMAMUX1_TIM4_CH2 30 -#define STM32_DMAMUX1_TIM4_CH3 31 -#define STM32_DMAMUX1_TIM4_UP 32 -#define STM32_DMAMUX1_I2C1_RX 33 -#define STM32_DMAMUX1_I2C1_TX 34 -#define STM32_DMAMUX1_I2C2_RX 35 -#define STM32_DMAMUX1_I2C2_TX 36 -#define STM32_DMAMUX1_SPI1_RX 37 -#define STM32_DMAMUX1_SPI1_TX 38 -#define STM32_DMAMUX1_SPI2_RX 39 -#define STM32_DMAMUX1_SPI2_TX 40 -#define STM32_DMAMUX1_USART1_RX 41 -#define STM32_DMAMUX1_USART1_TX 42 -#define STM32_DMAMUX1_USART2_RX 43 -#define STM32_DMAMUX1_USART2_TX 44 -#define STM32_DMAMUX1_USART3_RX 45 -#define STM32_DMAMUX1_USART3_TX 46 -#define STM32_DMAMUX1_TIM8_CH1 47 -#define STM32_DMAMUX1_TIM8_CH2 48 -#define STM32_DMAMUX1_TIM8_CH3 49 -#define STM32_DMAMUX1_TIM8_CH4 50 -#define STM32_DMAMUX1_TIM8_UP 51 -#define STM32_DMAMUX1_TIM8_TRIG 52 -#define STM32_DMAMUX1_TIM8_COM 53 -#define STM32_DMAMUX1_RESERVED54 54 -#define STM32_DMAMUX1_TIM5_CH1 55 -#define STM32_DMAMUX1_TIM5_CH2 56 -#define STM32_DMAMUX1_TIM5_CH3 57 -#define STM32_DMAMUX1_TIM5_CH4 58 -#define STM32_DMAMUX1_TIM5_UP 59 -#define STM32_DMAMUX1_TIM5_TRIG 60 -#define STM32_DMAMUX1_SPI3_RX 61 -#define STM32_DMAMUX1_SPI3_TX 62 -#define STM32_DMAMUX1_UART4_RX 63 -#define STM32_DMAMUX1_UART4_TX 64 -#define STM32_DMAMUX1_UART5_RX 65 -#define STM32_DMAMUX1_UART5_TX 66 -#define STM32_DMAMUX1_DAC1_CH1 67 /* Renamed to L4 name.*/ -#define STM32_DMAMUX1_DAC1_CH2 68 /* Renamed to L4 name.*/ -#define STM32_DMAMUX1_TIM6_UP 69 -#define STM32_DMAMUX1_TIM7_UP 70 -#define STM32_DMAMUX1_USART6_RX 71 -#define STM32_DMAMUX1_USART6_TX 72 -#define STM32_DMAMUX1_I2C3_RX 73 -#define STM32_DMAMUX1_I2C3_TX 74 -#define STM32_DMAMUX1_DCMI 75 -#define STM32_DMAMUX1_CRYP_IN 76 -#define STM32_DMAMUX1_CRYP_OUT 77 -#define STM32_DMAMUX1_HASH_IN 78 -#define STM32_DMAMUX1_UART7_RX 79 -#define STM32_DMAMUX1_UART7_TX 80 -#define STM32_DMAMUX1_UART8_RX 81 -#define STM32_DMAMUX1_UART8_TX 82 -#define STM32_DMAMUX1_SPI4_RX 83 -#define STM32_DMAMUX1_SPI4_TX 84 -#define STM32_DMAMUX1_SPI5_RX 85 -#define STM32_DMAMUX1_SPI5_TX 86 -#define STM32_DMAMUX1_SAI1_A 87 -#define STM32_DMAMUX1_SAI1_B 88 -#define STM32_DMAMUX1_SAI2_A 89 -#define STM32_DMAMUX1_SAI2_B 90 -#define STM32_DMAMUX1_SWPMI_RX 91 -#define STM32_DMAMUX1_SQPMI_TX 92 -#define STM32_DMAMUX1_SPDIFRX_DT 93 -#define STM32_DMAMUX1_SPDIFRX_CS 94 -#define STM32_DMAMUX1_HR_REQ1 95 -#define STM32_DMAMUX1_HR_REQ2 96 -#define STM32_DMAMUX1_HR_REQ3 97 -#define STM32_DMAMUX1_HR_REQ4 98 -#define STM32_DMAMUX1_HR_REQ5 99 -#define STM32_DMAMUX1_HR_REQ6 100 -#define STM32_DMAMUX1_DFSDM1_DMA0 101 -#define STM32_DMAMUX1_DFSDM1_DMA1 102 -#define STM32_DMAMUX1_DFSDM1_DMA2 103 -#define STM32_DMAMUX1_DFSDM1_DMA3 104 -#define STM32_DMAMUX1_TIM15_CH1 105 -#define STM32_DMAMUX1_TIM15_UP 106 -#define STM32_DMAMUX1_TIM15_TRIG 107 -#define STM32_DMAMUX1_TIM15_COM 108 -#define STM32_DMAMUX1_TIM16_CH1 109 -#define STM32_DMAMUX1_TIM16_UP 110 -#define STM32_DMAMUX1_TIM17_CH1 111 -#define STM32_DMAMUX1_TIM17_UP 112 -#define STM32_DMAMUX1_SAI3_A 113 -#define STM32_DMAMUX1_SAI3_B 114 -#define STM32_DMAMUX1_ADC3 115 -/** @} */ - -/** - * @name DMAMUX2 request sources - * @{ - */ -#define STM32_DMAMUX2_REQ_GEN0 1 -#define STM32_DMAMUX2_REQ_GEN1 2 -#define STM32_DMAMUX2_REQ_GEN2 3 -#define STM32_DMAMUX2_REQ_GEN3 4 -#define STM32_DMAMUX2_REQ_GEN4 5 -#define STM32_DMAMUX2_REQ_GEN5 6 -#define STM32_DMAMUX2_REQ_GEN6 7 -#define STM32_DMAMUX2_REQ_GEN7 8 -#define STM32_DMAMUX2_LP_UART1_RX 9 -#define STM32_DMAMUX2_LP_UART1_TX 10 -#define STM32_DMAMUX2_SPI6_RX 11 -#define STM32_DMAMUX2_SPI6_TX 12 -#define STM32_DMAMUX2_I2C4_RX 13 -#define STM32_DMAMUX2_I2C4_TX 14 -#define STM32_DMAMUX2_SAI4_A 15 -#define STM32_DMAMUX2_SAI4_B 16 -#define STM32_DMAMUX2_ADC3_REQ 17 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMAMUX_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32H7xx/stm32_dmamux.h + * @brief STM32H7xx DMAMUX handler header. + * + * @addtogroup STM32H7xx_DMAMUX + * @{ + */ + +#ifndef STM32_DMAMUX_H +#define STM32_DMAMUX_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name DMAMUX1 request sources + * @{ + */ +#define STM32_DMAMUX1_REQ_GEN0 1 +#define STM32_DMAMUX1_REQ_GEN1 2 +#define STM32_DMAMUX1_REQ_GEN2 3 +#define STM32_DMAMUX1_REQ_GEN3 4 +#define STM32_DMAMUX1_REQ_GEN4 5 +#define STM32_DMAMUX1_REQ_GEN5 6 +#define STM32_DMAMUX1_REQ_GEN6 7 +#define STM32_DMAMUX1_REQ_GEN7 8 +#define STM32_DMAMUX1_ADC1 9 +#define STM32_DMAMUX1_ADC2 10 +#define STM32_DMAMUX1_TIM1_CH1 11 +#define STM32_DMAMUX1_TIM1_CH2 12 +#define STM32_DMAMUX1_TIM1_CH3 13 +#define STM32_DMAMUX1_TIM1_CH4 14 +#define STM32_DMAMUX1_TIM1_UP 15 +#define STM32_DMAMUX1_TIM1_TRIG 16 +#define STM32_DMAMUX1_TIM1_COM 17 +#define STM32_DMAMUX1_TIM2_CH1 18 +#define STM32_DMAMUX1_TIM2_CH2 19 +#define STM32_DMAMUX1_TIM2_CH3 20 +#define STM32_DMAMUX1_TIM2_CH4 21 +#define STM32_DMAMUX1_TIM2_UP 22 +#define STM32_DMAMUX1_TIM3_CH1 23 +#define STM32_DMAMUX1_TIM3_CH2 24 +#define STM32_DMAMUX1_TIM3_CH3 25 +#define STM32_DMAMUX1_TIM3_CH4 26 +#define STM32_DMAMUX1_TIM3_UP 27 +#define STM32_DMAMUX1_TIM3_TRIG 28 +#define STM32_DMAMUX1_TIM4_CH1 29 +#define STM32_DMAMUX1_TIM4_CH2 30 +#define STM32_DMAMUX1_TIM4_CH3 31 +#define STM32_DMAMUX1_TIM4_UP 32 +#define STM32_DMAMUX1_I2C1_RX 33 +#define STM32_DMAMUX1_I2C1_TX 34 +#define STM32_DMAMUX1_I2C2_RX 35 +#define STM32_DMAMUX1_I2C2_TX 36 +#define STM32_DMAMUX1_SPI1_RX 37 +#define STM32_DMAMUX1_SPI1_TX 38 +#define STM32_DMAMUX1_SPI2_RX 39 +#define STM32_DMAMUX1_SPI2_TX 40 +#define STM32_DMAMUX1_USART1_RX 41 +#define STM32_DMAMUX1_USART1_TX 42 +#define STM32_DMAMUX1_USART2_RX 43 +#define STM32_DMAMUX1_USART2_TX 44 +#define STM32_DMAMUX1_USART3_RX 45 +#define STM32_DMAMUX1_USART3_TX 46 +#define STM32_DMAMUX1_TIM8_CH1 47 +#define STM32_DMAMUX1_TIM8_CH2 48 +#define STM32_DMAMUX1_TIM8_CH3 49 +#define STM32_DMAMUX1_TIM8_CH4 50 +#define STM32_DMAMUX1_TIM8_UP 51 +#define STM32_DMAMUX1_TIM8_TRIG 52 +#define STM32_DMAMUX1_TIM8_COM 53 +#define STM32_DMAMUX1_RESERVED54 54 +#define STM32_DMAMUX1_TIM5_CH1 55 +#define STM32_DMAMUX1_TIM5_CH2 56 +#define STM32_DMAMUX1_TIM5_CH3 57 +#define STM32_DMAMUX1_TIM5_CH4 58 +#define STM32_DMAMUX1_TIM5_UP 59 +#define STM32_DMAMUX1_TIM5_TRIG 60 +#define STM32_DMAMUX1_SPI3_RX 61 +#define STM32_DMAMUX1_SPI3_TX 62 +#define STM32_DMAMUX1_UART4_RX 63 +#define STM32_DMAMUX1_UART4_TX 64 +#define STM32_DMAMUX1_UART5_RX 65 +#define STM32_DMAMUX1_UART5_TX 66 +#define STM32_DMAMUX1_DAC1_CH1 67 /* Renamed to L4 name.*/ +#define STM32_DMAMUX1_DAC1_CH2 68 /* Renamed to L4 name.*/ +#define STM32_DMAMUX1_TIM6_UP 69 +#define STM32_DMAMUX1_TIM7_UP 70 +#define STM32_DMAMUX1_USART6_RX 71 +#define STM32_DMAMUX1_USART6_TX 72 +#define STM32_DMAMUX1_I2C3_RX 73 +#define STM32_DMAMUX1_I2C3_TX 74 +#define STM32_DMAMUX1_DCMI 75 +#define STM32_DMAMUX1_CRYP_IN 76 +#define STM32_DMAMUX1_CRYP_OUT 77 +#define STM32_DMAMUX1_HASH_IN 78 +#define STM32_DMAMUX1_UART7_RX 79 +#define STM32_DMAMUX1_UART7_TX 80 +#define STM32_DMAMUX1_UART8_RX 81 +#define STM32_DMAMUX1_UART8_TX 82 +#define STM32_DMAMUX1_SPI4_RX 83 +#define STM32_DMAMUX1_SPI4_TX 84 +#define STM32_DMAMUX1_SPI5_RX 85 +#define STM32_DMAMUX1_SPI5_TX 86 +#define STM32_DMAMUX1_SAI1_A 87 +#define STM32_DMAMUX1_SAI1_B 88 +#define STM32_DMAMUX1_SAI2_A 89 +#define STM32_DMAMUX1_SAI2_B 90 +#define STM32_DMAMUX1_SWPMI_RX 91 +#define STM32_DMAMUX1_SQPMI_TX 92 +#define STM32_DMAMUX1_SPDIFRX_DT 93 +#define STM32_DMAMUX1_SPDIFRX_CS 94 +#define STM32_DMAMUX1_HR_REQ1 95 +#define STM32_DMAMUX1_HR_REQ2 96 +#define STM32_DMAMUX1_HR_REQ3 97 +#define STM32_DMAMUX1_HR_REQ4 98 +#define STM32_DMAMUX1_HR_REQ5 99 +#define STM32_DMAMUX1_HR_REQ6 100 +#define STM32_DMAMUX1_DFSDM1_DMA0 101 +#define STM32_DMAMUX1_DFSDM1_DMA1 102 +#define STM32_DMAMUX1_DFSDM1_DMA2 103 +#define STM32_DMAMUX1_DFSDM1_DMA3 104 +#define STM32_DMAMUX1_TIM15_CH1 105 +#define STM32_DMAMUX1_TIM15_UP 106 +#define STM32_DMAMUX1_TIM15_TRIG 107 +#define STM32_DMAMUX1_TIM15_COM 108 +#define STM32_DMAMUX1_TIM16_CH1 109 +#define STM32_DMAMUX1_TIM16_UP 110 +#define STM32_DMAMUX1_TIM17_CH1 111 +#define STM32_DMAMUX1_TIM17_UP 112 +#define STM32_DMAMUX1_SAI3_A 113 +#define STM32_DMAMUX1_SAI3_B 114 +#define STM32_DMAMUX1_ADC3 115 +/** @} */ + +/** + * @name DMAMUX2 request sources + * @{ + */ +#define STM32_DMAMUX2_REQ_GEN0 1 +#define STM32_DMAMUX2_REQ_GEN1 2 +#define STM32_DMAMUX2_REQ_GEN2 3 +#define STM32_DMAMUX2_REQ_GEN3 4 +#define STM32_DMAMUX2_REQ_GEN4 5 +#define STM32_DMAMUX2_REQ_GEN5 6 +#define STM32_DMAMUX2_REQ_GEN6 7 +#define STM32_DMAMUX2_REQ_GEN7 8 +#define STM32_DMAMUX2_LP_UART1_RX 9 +#define STM32_DMAMUX2_LP_UART1_TX 10 +#define STM32_DMAMUX2_SPI6_RX 11 +#define STM32_DMAMUX2_SPI6_TX 12 +#define STM32_DMAMUX2_I2C4_RX 13 +#define STM32_DMAMUX2_I2C4_TX 14 +#define STM32_DMAMUX2_SAI4_A 15 +#define STM32_DMAMUX2_SAI4_B 16 +#define STM32_DMAMUX2_ADC3_REQ 17 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMAMUX_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_isr.c b/os/hal/ports/STM32/STM32H7xx/stm32_isr.c index 8ed4d72fc7..aea191e691 100644 --- a/os/hal/ports/STM32/STM32H7xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32H7xx/stm32_isr.c @@ -1,198 +1,198 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32H7xx/stm32_isr.c - * @brief STM32H7xx ISR handler code. - * - * @addtogroup STM32H7xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_exti0.inc" -#include "stm32_exti1.inc" -#include "stm32_exti2.inc" -#include "stm32_exti3.inc" -#include "stm32_exti4.inc" -#include "stm32_exti5_9.inc" -#include "stm32_exti10_15.inc" -#include "stm32_exti16.inc" -#include "stm32_exti17.inc" -#include "stm32_exti18.inc" -#include "stm32_exti19.inc" -#include "stm32_exti20_21.inc" - -#include "stm32_fdcan1.inc" -#include "stm32_fdcan2.inc" - -#include "stm32_quadspi1.inc" - -#include "stm32_sdmmc1.inc" -#include "stm32_sdmmc2.inc" - -#include -#include "stm32_usart2.inc" -#include "stm32_usart3.inc" -#include "stm32_uart4.inc" -#include "stm32_uart5.inc" -#include "stm32_usart6.inc" -#include "stm32_uart7.inc" -#include "stm32_uart8.inc" -#include "stm32_lpuart1.inc" - -#include "stm32_tim1.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim4.inc" -#include "stm32_tim5.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim8_12_13_14.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_irq_init(); - exti1_irq_init(); - exti2_irq_init(); - exti3_irq_init(); - exti4_irq_init(); - exti5_9_irq_init(); - exti10_15_irq_init(); - exti16_irq_init(); - exti17_irq_init(); - exti18_irq_init(); - exti19_irq_init(); - exti20_exti21_irq_init(); - - fdcan1_irq_init(); - fdcan2_irq_init(); - - mdma_irq_init(); - - quadspi1_irq_init(); - - sdmmc1_irq_init(); - sdmmc2_irq_init(); - - tim1_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim4_irq_init(); - tim5_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim8_tim12_tim13_tim14_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_irq_init(); - uart4_irq_init(); - uart5_irq_init(); - usart6_irq_init(); - uart7_irq_init(); - uart8_irq_init(); - lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_irq_deinit(); - exti1_irq_deinit(); - exti2_irq_deinit(); - exti3_irq_deinit(); - exti4_irq_deinit(); - exti5_9_irq_deinit(); - exti10_15_irq_deinit(); - exti16_irq_deinit(); - exti17_irq_deinit(); - exti18_irq_deinit(); - exti19_irq_deinit(); - exti20_exti21_irq_deinit(); - - fdcan1_irq_deinit(); - fdcan2_irq_deinit(); - - mdma_irq_deinit(); - - quadspi1_irq_deinit(); - - sdmmc1_irq_deinit(); - sdmmc2_irq_deinit(); - - tim1_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim4_irq_deinit(); - tim5_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim8_tim12_tim13_tim14_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_irq_deinit(); - uart4_irq_deinit(); - uart5_irq_deinit(); - usart6_irq_deinit(); - uart7_irq_deinit(); - uart8_irq_deinit(); - lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32H7xx/stm32_isr.c + * @brief STM32H7xx ISR handler code. + * + * @addtogroup STM32H7xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_exti0.inc" +#include "stm32_exti1.inc" +#include "stm32_exti2.inc" +#include "stm32_exti3.inc" +#include "stm32_exti4.inc" +#include "stm32_exti5_9.inc" +#include "stm32_exti10_15.inc" +#include "stm32_exti16.inc" +#include "stm32_exti17.inc" +#include "stm32_exti18.inc" +#include "stm32_exti19.inc" +#include "stm32_exti20_21.inc" + +#include "stm32_fdcan1.inc" +#include "stm32_fdcan2.inc" + +#include "stm32_quadspi1.inc" + +#include "stm32_sdmmc1.inc" +#include "stm32_sdmmc2.inc" + +#include +#include "stm32_usart2.inc" +#include "stm32_usart3.inc" +#include "stm32_uart4.inc" +#include "stm32_uart5.inc" +#include "stm32_usart6.inc" +#include "stm32_uart7.inc" +#include "stm32_uart8.inc" +#include "stm32_lpuart1.inc" + +#include "stm32_tim1.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim4.inc" +#include "stm32_tim5.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim8_12_13_14.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_irq_init(); + exti1_irq_init(); + exti2_irq_init(); + exti3_irq_init(); + exti4_irq_init(); + exti5_9_irq_init(); + exti10_15_irq_init(); + exti16_irq_init(); + exti17_irq_init(); + exti18_irq_init(); + exti19_irq_init(); + exti20_exti21_irq_init(); + + fdcan1_irq_init(); + fdcan2_irq_init(); + + mdma_irq_init(); + + quadspi1_irq_init(); + + sdmmc1_irq_init(); + sdmmc2_irq_init(); + + tim1_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim4_irq_init(); + tim5_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim8_tim12_tim13_tim14_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_irq_init(); + uart4_irq_init(); + uart5_irq_init(); + usart6_irq_init(); + uart7_irq_init(); + uart8_irq_init(); + lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_irq_deinit(); + exti1_irq_deinit(); + exti2_irq_deinit(); + exti3_irq_deinit(); + exti4_irq_deinit(); + exti5_9_irq_deinit(); + exti10_15_irq_deinit(); + exti16_irq_deinit(); + exti17_irq_deinit(); + exti18_irq_deinit(); + exti19_irq_deinit(); + exti20_exti21_irq_deinit(); + + fdcan1_irq_deinit(); + fdcan2_irq_deinit(); + + mdma_irq_deinit(); + + quadspi1_irq_deinit(); + + sdmmc1_irq_deinit(); + sdmmc2_irq_deinit(); + + tim1_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim4_irq_deinit(); + tim5_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim8_tim12_tim13_tim14_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_irq_deinit(); + uart4_irq_deinit(); + uart5_irq_deinit(); + usart6_irq_deinit(); + uart7_irq_deinit(); + uart8_irq_deinit(); + lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_isr.h b/os/hal/ports/STM32/STM32H7xx/stm32_isr.h index a51b10a6dc..fe7dfd924d 100644 --- a/os/hal/ports/STM32/STM32H7xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32H7xx/stm32_isr.h @@ -1,384 +1,384 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32H7xx/stm32_isr.h - * @brief STM32H7xx ISR handler header. - * - * @addtogroup STM32H7xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM8_SUPPRESS_ISR -#define STM32_TIM12_SUPPRESS_ISR -#define STM32_TIM13_SUPPRESS_ISR -#define STM32_TIM14_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_USART6_SUPPRESS_ISR -#define STM32_UART7_SUPPRESS_ISR -#define STM32_UART8_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC units. - */ -#define STM32_ADC12_HANDLER Vector88 -#define STM32_ADC3_HANDLER Vector23C - -#define STM32_ADC12_NUMBER 18 -#define STM32_ADC3_NUMBER 127 - -/* - * BDMA units. - */ -#define STM32_BDMA1_CH0_HANDLER Vector244 -#define STM32_BDMA1_CH1_HANDLER Vector248 -#define STM32_BDMA1_CH2_HANDLER Vector24C -#define STM32_BDMA1_CH3_HANDLER Vector250 -#define STM32_BDMA1_CH4_HANDLER Vector254 -#define STM32_BDMA1_CH5_HANDLER Vector258 -#define STM32_BDMA1_CH6_HANDLER Vector25C -#define STM32_BDMA1_CH7_HANDLER Vector260 - -#define STM32_BDMA1_CH0_NUMBER 129 -#define STM32_BDMA1_CH1_NUMBER 130 -#define STM32_BDMA1_CH2_NUMBER 131 -#define STM32_BDMA1_CH3_NUMBER 132 -#define STM32_BDMA1_CH4_NUMBER 133 -#define STM32_BDMA1_CH5_NUMBER 134 -#define STM32_BDMA1_CH6_NUMBER 135 -#define STM32_BDMA1_CH7_NUMBER 136 - -/* - * DMA units. - */ -#define STM32_DMA1_CH0_HANDLER Vector6C -#define STM32_DMA1_CH1_HANDLER Vector70 -#define STM32_DMA1_CH2_HANDLER Vector74 -#define STM32_DMA1_CH3_HANDLER Vector78 -#define STM32_DMA1_CH4_HANDLER Vector7C -#define STM32_DMA1_CH5_HANDLER Vector80 -#define STM32_DMA1_CH6_HANDLER Vector84 -#define STM32_DMA1_CH7_HANDLER VectorFC -#define STM32_DMA2_CH0_HANDLER Vector120 -#define STM32_DMA2_CH1_HANDLER Vector124 -#define STM32_DMA2_CH2_HANDLER Vector128 -#define STM32_DMA2_CH3_HANDLER Vector12C -#define STM32_DMA2_CH4_HANDLER Vector130 -#define STM32_DMA2_CH5_HANDLER Vector150 -#define STM32_DMA2_CH6_HANDLER Vector154 -#define STM32_DMA2_CH7_HANDLER Vector158 - -#define STM32_DMA1_CH0_NUMBER 11 -#define STM32_DMA1_CH1_NUMBER 12 -#define STM32_DMA1_CH2_NUMBER 13 -#define STM32_DMA1_CH3_NUMBER 14 -#define STM32_DMA1_CH4_NUMBER 15 -#define STM32_DMA1_CH5_NUMBER 16 -#define STM32_DMA1_CH6_NUMBER 17 -#define STM32_DMA1_CH7_NUMBER 47 -#define STM32_DMA2_CH0_NUMBER 56 -#define STM32_DMA2_CH1_NUMBER 57 -#define STM32_DMA2_CH2_NUMBER 58 -#define STM32_DMA2_CH3_NUMBER 59 -#define STM32_DMA2_CH4_NUMBER 60 -#define STM32_DMA2_CH5_NUMBER 68 -#define STM32_DMA2_CH6_NUMBER 69 -#define STM32_DMA2_CH7_NUMBER 70 - -/* - * MDMA units. - */ -#define STM32_MDMA_HANDLER Vector228 - -#define STM32_MDMA_NUMBER 122 - -/* - * ETH units. - */ -#define STM32_ETH_HANDLER Vector134 - -#define STM32_ETH_NUMBER 61 - -/* - * EXTI units. - */ -#define STM32_EXTI0_HANDLER Vector58 -#define STM32_EXTI1_HANDLER Vector5C -#define STM32_EXTI2_HANDLER Vector60 -#define STM32_EXTI3_HANDLER Vector64 -#define STM32_EXTI4_HANDLER Vector68 -#define STM32_EXTI5_9_HANDLER Vector9C -#define STM32_EXTI10_15_HANDLER VectorE0 -#define STM32_EXTI16_HANDLER Vector44 /* PVD */ -#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */ -#define STM32_EXTI18_HANDLER Vector48 /* RTC TAMP CSS */ -#define STM32_EXTI19_HANDLER Vector4C /* RTC WAKEUP */ -#define STM32_EXTI2021_HANDLER Vector264 /* COMP1 COMP2 */ - -#define STM32_EXTI0_NUMBER 6 -#define STM32_EXTI1_NUMBER 7 -#define STM32_EXTI2_NUMBER 8 -#define STM32_EXTI3_NUMBER 9 -#define STM32_EXTI4_NUMBER 10 -#define STM32_EXTI5_9_NUMBER 23 -#define STM32_EXTI10_15_NUMBER 40 -#define STM32_EXTI16_NUMBER 1 -#define STM32_EXTI17_NUMBER 41 -#define STM32_EXTI18_NUMBER 42 -#define STM32_EXTI19_NUMBER 3 -#define STM32_EXTI2021_NUMBER 137 - -/* - * FDCAN units. - */ -#define STM32_FDCAN1_IT0_HANDLER Vector8C -#define STM32_FDCAN1_IT1_HANDLER Vector94 -#define STM32_FDCAN2_IT0_HANDLER Vector90 -#define STM32_FDCAN2_IT1_HANDLER Vector98 - -#define STM32_FDCAN1_IT0_NUMBER 19 -#define STM32_FDCAN1_IT1_NUMBER 21 -#define STM32_FDCAN2_IT0_NUMBER 20 -#define STM32_FDCAN2_IT1_NUMBER 22 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C3_EVENT_HANDLER Vector160 -#define STM32_I2C3_ERROR_HANDLER Vector164 -#define STM32_I2C4_EVENT_HANDLER Vector1BC -#define STM32_I2C4_ERROR_HANDLER Vector1C0 - -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 -#define STM32_I2C3_EVENT_NUMBER 72 -#define STM32_I2C3_ERROR_NUMBER 73 -#define STM32_I2C4_EVENT_NUMBER 95 -#define STM32_I2C4_ERROR_NUMBER 96 - -/* - * QUADSPI units. - */ -#define STM32_QUADSPI1_HANDLER Vector1B0 - -#define STM32_QUADSPI1_NUMBER 92 - -/* - * SDMMC units. - */ -#define STM32_SDMMC1_HANDLER Vector104 -#define STM32_SDMMC2_HANDLER Vector230 - -#define STM32_SDMMC1_NUMBER 49 -#define STM32_SDMMC2_NUMBER 124 - -/* - * SPI units. - */ -#define STM32_SPI1_HANDLER VectorCC -#define STM32_SPI2_HANDLER VectorD0 -#define STM32_SPI3_HANDLER Vector10C -#define STM32_SPI4_HANDLER Vector190 -#define STM32_SPI5_HANDLER Vector194 -#define STM32_SPI6_HANDLER Vector198 - -#define STM32_SPI1_NUMBER 35 -#define STM32_SPI2_NUMBER 36 -#define STM32_SPI3_NUMBER 51 -#define STM32_SPI4_NUMBER 84 -#define STM32_SPI5_NUMBER 85 -#define STM32_SPI6_NUMBER 86 - -/* - * TIM units. - */ -#define STM32_TIM1_BRK_HANDLER VectorA0 -#define STM32_TIM1_UP_HANDLER VectorA4 -#define STM32_TIM1_TRGCO_HANDLER VectorA8 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_BRK_TIM12_HANDLER VectorEC -#define STM32_TIM8_UP_TIM13_HANDLER VectorF0 -#define STM32_TIM8_TRGCO_TIM14_HANDLER VectorF4 -#define STM32_TIM8_CC_HANDLER VectorF8 -#define STM32_TIM15_HANDLER Vector210 -#define STM32_TIM16_HANDLER Vector214 -#define STM32_TIM17_HANDLER Vector218 - -#define STM32_TIM1_BRK_NUMBER 24 -#define STM32_TIM1_UP_NUMBER 25 -#define STM32_TIM1_TRGCO_NUMBER 26 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_BRK_TIM12_NUMBER 43 -#define STM32_TIM8_UP_TIM13_NUMBER 44 -#define STM32_TIM8_TRGCO_TIM14_NUMBER 45 -#define STM32_TIM8_CC_NUMBER 46 -#define STM32_TIM15_NUMBER 116 -#define STM32_TIM16_NUMBER 117 -#define STM32_TIM17_NUMBER 118 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_USART6_HANDLER Vector15C -#define STM32_UART7_HANDLER Vector188 -#define STM32_UART8_HANDLER Vector18C -#define STM32_LPUART1_HANDLER Vector278 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_USART6_NUMBER 71 -#define STM32_UART7_NUMBER 82 -#define STM32_UART8_NUMBER 83 -#define STM32_LPUART1_NUMBER 142 - -/* - * USB/OTG units. - */ -#define STM32_OTG1_HANDLER Vector1D4 -#define STM32_OTG1_EP1OUT_HANDLER Vector1C8 -#define STM32_OTG1_EP1IN_HANDLER Vector1CC -#define STM32_OTG2_HANDLER Vector174 -#define STM32_OTG2_EP1OUT_HANDLER Vector168 -#define STM32_OTG2_EP1IN_HANDLER Vector16C - -#define STM32_OTG1_NUMBER 101 -#define STM32_OTG1_EP1OUT_NUMBER 98 -#define STM32_OTG1_EP1IN_NUMBER 99 -#define STM32_OTG2_NUMBER 77 -#define STM32_OTG2_EP1OUT_NUMBER 74 -#define STM32_OTG2_EP1IN_NUMBER 75 - -/* - * LTDC units. - */ -#define STM32_LTDC_EV_HANDLER Vector1A0 -#define STM32_LTDC_ER_HANDLER Vector1A4 - -#define STM32_LTDC_EV_NUMBER 88 -#define STM32_LTDC_ER_NUMBER 89 - -/* - * DMA2D units. - */ -#define STM32_DMA2D_HANDLER Vector1A8 - -#define STM32_DMA2D_NUMBER 90 - -/* - * FSMC units. - */ -#define STM32_FSMC_HANDLER Vector100 - -#define STM32_FSMC_NUMBER 48 - -/* - * DCMI units. - */ -#define STM32_DCMI_HANDLER Vector178 - -#define STM32_DCMI_NUMBER 78 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32H7xx/stm32_isr.h + * @brief STM32H7xx ISR handler header. + * + * @addtogroup STM32H7xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM8_SUPPRESS_ISR +#define STM32_TIM12_SUPPRESS_ISR +#define STM32_TIM13_SUPPRESS_ISR +#define STM32_TIM14_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_USART6_SUPPRESS_ISR +#define STM32_UART7_SUPPRESS_ISR +#define STM32_UART8_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC units. + */ +#define STM32_ADC12_HANDLER Vector88 +#define STM32_ADC3_HANDLER Vector23C + +#define STM32_ADC12_NUMBER 18 +#define STM32_ADC3_NUMBER 127 + +/* + * BDMA units. + */ +#define STM32_BDMA1_CH0_HANDLER Vector244 +#define STM32_BDMA1_CH1_HANDLER Vector248 +#define STM32_BDMA1_CH2_HANDLER Vector24C +#define STM32_BDMA1_CH3_HANDLER Vector250 +#define STM32_BDMA1_CH4_HANDLER Vector254 +#define STM32_BDMA1_CH5_HANDLER Vector258 +#define STM32_BDMA1_CH6_HANDLER Vector25C +#define STM32_BDMA1_CH7_HANDLER Vector260 + +#define STM32_BDMA1_CH0_NUMBER 129 +#define STM32_BDMA1_CH1_NUMBER 130 +#define STM32_BDMA1_CH2_NUMBER 131 +#define STM32_BDMA1_CH3_NUMBER 132 +#define STM32_BDMA1_CH4_NUMBER 133 +#define STM32_BDMA1_CH5_NUMBER 134 +#define STM32_BDMA1_CH6_NUMBER 135 +#define STM32_BDMA1_CH7_NUMBER 136 + +/* + * DMA units. + */ +#define STM32_DMA1_CH0_HANDLER Vector6C +#define STM32_DMA1_CH1_HANDLER Vector70 +#define STM32_DMA1_CH2_HANDLER Vector74 +#define STM32_DMA1_CH3_HANDLER Vector78 +#define STM32_DMA1_CH4_HANDLER Vector7C +#define STM32_DMA1_CH5_HANDLER Vector80 +#define STM32_DMA1_CH6_HANDLER Vector84 +#define STM32_DMA1_CH7_HANDLER VectorFC +#define STM32_DMA2_CH0_HANDLER Vector120 +#define STM32_DMA2_CH1_HANDLER Vector124 +#define STM32_DMA2_CH2_HANDLER Vector128 +#define STM32_DMA2_CH3_HANDLER Vector12C +#define STM32_DMA2_CH4_HANDLER Vector130 +#define STM32_DMA2_CH5_HANDLER Vector150 +#define STM32_DMA2_CH6_HANDLER Vector154 +#define STM32_DMA2_CH7_HANDLER Vector158 + +#define STM32_DMA1_CH0_NUMBER 11 +#define STM32_DMA1_CH1_NUMBER 12 +#define STM32_DMA1_CH2_NUMBER 13 +#define STM32_DMA1_CH3_NUMBER 14 +#define STM32_DMA1_CH4_NUMBER 15 +#define STM32_DMA1_CH5_NUMBER 16 +#define STM32_DMA1_CH6_NUMBER 17 +#define STM32_DMA1_CH7_NUMBER 47 +#define STM32_DMA2_CH0_NUMBER 56 +#define STM32_DMA2_CH1_NUMBER 57 +#define STM32_DMA2_CH2_NUMBER 58 +#define STM32_DMA2_CH3_NUMBER 59 +#define STM32_DMA2_CH4_NUMBER 60 +#define STM32_DMA2_CH5_NUMBER 68 +#define STM32_DMA2_CH6_NUMBER 69 +#define STM32_DMA2_CH7_NUMBER 70 + +/* + * MDMA units. + */ +#define STM32_MDMA_HANDLER Vector228 + +#define STM32_MDMA_NUMBER 122 + +/* + * ETH units. + */ +#define STM32_ETH_HANDLER Vector134 + +#define STM32_ETH_NUMBER 61 + +/* + * EXTI units. + */ +#define STM32_EXTI0_HANDLER Vector58 +#define STM32_EXTI1_HANDLER Vector5C +#define STM32_EXTI2_HANDLER Vector60 +#define STM32_EXTI3_HANDLER Vector64 +#define STM32_EXTI4_HANDLER Vector68 +#define STM32_EXTI5_9_HANDLER Vector9C +#define STM32_EXTI10_15_HANDLER VectorE0 +#define STM32_EXTI16_HANDLER Vector44 /* PVD */ +#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */ +#define STM32_EXTI18_HANDLER Vector48 /* RTC TAMP CSS */ +#define STM32_EXTI19_HANDLER Vector4C /* RTC WAKEUP */ +#define STM32_EXTI2021_HANDLER Vector264 /* COMP1 COMP2 */ + +#define STM32_EXTI0_NUMBER 6 +#define STM32_EXTI1_NUMBER 7 +#define STM32_EXTI2_NUMBER 8 +#define STM32_EXTI3_NUMBER 9 +#define STM32_EXTI4_NUMBER 10 +#define STM32_EXTI5_9_NUMBER 23 +#define STM32_EXTI10_15_NUMBER 40 +#define STM32_EXTI16_NUMBER 1 +#define STM32_EXTI17_NUMBER 41 +#define STM32_EXTI18_NUMBER 42 +#define STM32_EXTI19_NUMBER 3 +#define STM32_EXTI2021_NUMBER 137 + +/* + * FDCAN units. + */ +#define STM32_FDCAN1_IT0_HANDLER Vector8C +#define STM32_FDCAN1_IT1_HANDLER Vector94 +#define STM32_FDCAN2_IT0_HANDLER Vector90 +#define STM32_FDCAN2_IT1_HANDLER Vector98 + +#define STM32_FDCAN1_IT0_NUMBER 19 +#define STM32_FDCAN1_IT1_NUMBER 21 +#define STM32_FDCAN2_IT0_NUMBER 20 +#define STM32_FDCAN2_IT1_NUMBER 22 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C3_EVENT_HANDLER Vector160 +#define STM32_I2C3_ERROR_HANDLER Vector164 +#define STM32_I2C4_EVENT_HANDLER Vector1BC +#define STM32_I2C4_ERROR_HANDLER Vector1C0 + +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 +#define STM32_I2C3_EVENT_NUMBER 72 +#define STM32_I2C3_ERROR_NUMBER 73 +#define STM32_I2C4_EVENT_NUMBER 95 +#define STM32_I2C4_ERROR_NUMBER 96 + +/* + * QUADSPI units. + */ +#define STM32_QUADSPI1_HANDLER Vector1B0 + +#define STM32_QUADSPI1_NUMBER 92 + +/* + * SDMMC units. + */ +#define STM32_SDMMC1_HANDLER Vector104 +#define STM32_SDMMC2_HANDLER Vector230 + +#define STM32_SDMMC1_NUMBER 49 +#define STM32_SDMMC2_NUMBER 124 + +/* + * SPI units. + */ +#define STM32_SPI1_HANDLER VectorCC +#define STM32_SPI2_HANDLER VectorD0 +#define STM32_SPI3_HANDLER Vector10C +#define STM32_SPI4_HANDLER Vector190 +#define STM32_SPI5_HANDLER Vector194 +#define STM32_SPI6_HANDLER Vector198 + +#define STM32_SPI1_NUMBER 35 +#define STM32_SPI2_NUMBER 36 +#define STM32_SPI3_NUMBER 51 +#define STM32_SPI4_NUMBER 84 +#define STM32_SPI5_NUMBER 85 +#define STM32_SPI6_NUMBER 86 + +/* + * TIM units. + */ +#define STM32_TIM1_BRK_HANDLER VectorA0 +#define STM32_TIM1_UP_HANDLER VectorA4 +#define STM32_TIM1_TRGCO_HANDLER VectorA8 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_BRK_TIM12_HANDLER VectorEC +#define STM32_TIM8_UP_TIM13_HANDLER VectorF0 +#define STM32_TIM8_TRGCO_TIM14_HANDLER VectorF4 +#define STM32_TIM8_CC_HANDLER VectorF8 +#define STM32_TIM15_HANDLER Vector210 +#define STM32_TIM16_HANDLER Vector214 +#define STM32_TIM17_HANDLER Vector218 + +#define STM32_TIM1_BRK_NUMBER 24 +#define STM32_TIM1_UP_NUMBER 25 +#define STM32_TIM1_TRGCO_NUMBER 26 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_BRK_TIM12_NUMBER 43 +#define STM32_TIM8_UP_TIM13_NUMBER 44 +#define STM32_TIM8_TRGCO_TIM14_NUMBER 45 +#define STM32_TIM8_CC_NUMBER 46 +#define STM32_TIM15_NUMBER 116 +#define STM32_TIM16_NUMBER 117 +#define STM32_TIM17_NUMBER 118 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_USART6_HANDLER Vector15C +#define STM32_UART7_HANDLER Vector188 +#define STM32_UART8_HANDLER Vector18C +#define STM32_LPUART1_HANDLER Vector278 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_USART6_NUMBER 71 +#define STM32_UART7_NUMBER 82 +#define STM32_UART8_NUMBER 83 +#define STM32_LPUART1_NUMBER 142 + +/* + * USB/OTG units. + */ +#define STM32_OTG1_HANDLER Vector1D4 +#define STM32_OTG1_EP1OUT_HANDLER Vector1C8 +#define STM32_OTG1_EP1IN_HANDLER Vector1CC +#define STM32_OTG2_HANDLER Vector174 +#define STM32_OTG2_EP1OUT_HANDLER Vector168 +#define STM32_OTG2_EP1IN_HANDLER Vector16C + +#define STM32_OTG1_NUMBER 101 +#define STM32_OTG1_EP1OUT_NUMBER 98 +#define STM32_OTG1_EP1IN_NUMBER 99 +#define STM32_OTG2_NUMBER 77 +#define STM32_OTG2_EP1OUT_NUMBER 74 +#define STM32_OTG2_EP1IN_NUMBER 75 + +/* + * LTDC units. + */ +#define STM32_LTDC_EV_HANDLER Vector1A0 +#define STM32_LTDC_ER_HANDLER Vector1A4 + +#define STM32_LTDC_EV_NUMBER 88 +#define STM32_LTDC_ER_NUMBER 89 + +/* + * DMA2D units. + */ +#define STM32_DMA2D_HANDLER Vector1A8 + +#define STM32_DMA2D_NUMBER 90 + +/* + * FSMC units. + */ +#define STM32_FSMC_HANDLER Vector100 + +#define STM32_FSMC_NUMBER 48 + +/* + * DCMI units. + */ +#define STM32_DCMI_HANDLER Vector178 + +#define STM32_DCMI_NUMBER 78 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h b/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h index 1b78dbb80b..c9ebfb9eda 100644 --- a/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h @@ -1,1907 +1,1907 @@ -/* - ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F7xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f7xx.h. - * - * @addtogroup STM32F7xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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, low set - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1L(mask, lp) { \ - RCC->APB1LENR |= (mask); \ - if (lp) \ - RCC->APB1LLPENR |= (mask); \ - else \ - RCC->APB1LLPENR &= ~(mask); \ - (void)RCC->APB1LLPENR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask, high set - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1H(mask, lp) { \ - RCC->APB1HENR |= (mask); \ - if (lp) \ - RCC->APB1HLPENR |= (mask); \ - else \ - RCC->APB1HLPENR &= ~(mask); \ - (void)RCC->APB1HLPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask, low set - * - * @api - */ -#define rccDisableAPB1L(mask) { \ - RCC->APB1LENR &= ~(mask); \ - RCC->APB1LLPENR &= ~(mask); \ - (void)RCC->APB1LLPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask, high set - * - * @api - */ -#define rccDisableAPB1H(mask) { \ - RCC->APB1HENR &= ~(mask); \ - RCC->APB1HLPENR &= ~(mask); \ - (void)RCC->APB1HLPENR; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask, low set - * - * @api - */ -#define rccResetAPB1L(mask) { \ - RCC->APB1LRSTR |= (mask); \ - RCC->APB1LRSTR &= ~(mask); \ - (void)RCC->APB1LRSTR; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask, high set - * - * @api - */ -#define rccResetAPB1H(mask) { \ - RCC->APB1HRSTR |= (mask); \ - RCC->APB1HRSTR &= ~(mask); \ - (void)RCC->APB1HRSTR; \ -} - -/** - * @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); \ - else \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB3 bus. - * - * @param[in] mask APB3 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB3(mask, lp) { \ - RCC->APB3ENR |= (mask); \ - if (lp) \ - RCC->APB3LPENR |= (mask); \ - else \ - RCC->APB3LPENR &= ~(mask); \ - (void)RCC->APB3LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB3 bus. - * - * @param[in] mask APB3 peripherals mask - * - * @api - */ -#define rccDisableAPB3(mask) { \ - RCC->APB3ENR &= ~(mask); \ - RCC->APB3LPENR &= ~(mask); \ - (void)RCC->APB3LPENR; \ -} - -/** - * @brief Resets one or more peripheral on the APB3 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccResetAPB3(mask) { \ - RCC->APB3RSTR |= (mask); \ - RCC->APB3RSTR &= ~(mask); \ - (void)RCC->APB3RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB4 bus. - * - * @param[in] mask APB4 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB4(mask, lp) { \ - RCC->APB4ENR |= (mask); \ - if (lp) \ - RCC->APB4LPENR |= (mask); \ - else \ - RCC->APB4LPENR &= ~(mask); \ - (void)RCC->APB4LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB4 bus. - * - * @param[in] mask APB4 peripherals mask - * - * @api - */ -#define rccDisableAPB4(mask) { \ - RCC->APB4ENR &= ~(mask); \ - RCC->APB4LPENR &= ~(mask); \ - (void)RCC->APB4LPENR; \ -} - -/** - * @brief Resets one or more peripheral on the APB4 bus. - * - * @param[in] mask APB4 peripherals mask - * - * @api - */ -#define rccResetAPB4(mask) { \ - RCC->APB4RSTR |= (mask); \ - RCC->APB4RSTR &= ~(mask); \ - (void)RCC->APB4RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB1LPENR &= ~(mask); \ - (void)RCC->AHB1LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1LPENR &= ~(mask); \ - (void)RCC->AHB1LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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); \ - else \ - RCC->AHB2LPENR &= ~(mask); \ - (void)RCC->AHB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2LPENR &= ~(mask); \ - (void)RCC->AHB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB3 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); \ - else \ - RCC->AHB3LPENR &= ~(mask); \ - (void)RCC->AHB3LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3LPENR &= ~(mask); \ - (void)RCC->AHB3LPENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB3 bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccResetAHB3(mask) { \ - RCC->AHB3RSTR |= (mask); \ - RCC->AHB3RSTR &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB4 bus. - * - * @param[in] mask AHB4 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB4(mask, lp) { \ - RCC->AHB4ENR |= (mask); \ - if (lp) \ - RCC->AHB4LPENR |= (mask); \ - else \ - RCC->AHB4LPENR &= ~(mask); \ - (void)RCC->AHB4LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB4 bus. - * - * @param[in] mask AHB4 peripherals mask - * - * @api - */ -#define rccDisableAHB4(mask) { \ - RCC->AHB4ENR &= ~(mask); \ - RCC->AHB4LPENR &= ~(mask); \ - (void)RCC->AHB4LPENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB4 bus. - * - * @param[in] mask AHB4 peripherals mask - * - * @api - */ -#define rccResetAHB4(mask) { \ - RCC->AHB4RSTR |= (mask); \ - RCC->AHB4RSTR &= ~(mask); \ - (void)RCC->AHB4RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC12(lp) rccEnableAHB1(RCC_AHB1ENR_ADC12EN, lp) - -/** - * @brief Disables the ADC1/ADC2 peripheral clock. - * - * @api - */ -#define rccDisableADC12() rccDisableAHB1(RCC_AHB1ENR_ADC12EN) - -/** - * @brief Resets the ADC1/ADC2 peripheral. - * - * @api - */ -#define rccResetADC12() rccResetAHB1(RCC_AHB1RSTR_ADC12RST) - -/** - * @brief Enables the ADC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC3(lp) rccEnableAHB4(RCC_AHB4ENR_ADC3EN, lp) - -/** - * @brief Disables the ADC3 peripheral clock. - * - * @api - */ -#define rccDisableADC3() rccDisableAHB4(RCC_AHB4ENR_ADC3EN) - -/** - * @brief Resets the ADC3 peripheral. - * - * @api - */ -#define rccResetADC3() rccResetAHB4(RCC_AHB4RSTR_ADC3RST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB4(RCC_AHB4ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB4(RCC_AHB4ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB4(RCC_AHB4RSTR_CRCRST) -/** @} */ - -/** - * @name CRYP peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRYP peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRYP(lp) rccEnableAHB2(RCC_AHB2ENR_CRYPEN, lp) - -/** - * @brief Disables the CRYP peripheral clock. - * - * @api - */ -#define rccDisableCRYP() rccDisableAHB2(RCC_AHB2ENR_CRYPEN) - -/** - * @brief Resets the CRYP peripheral. - * - * @api - */ -#define rccResetCRYP() rccResetAHB2(RCC_AHB2RSTR_CRYPRST) -/** @} */ - -/** - * @name HASH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the HASH peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableHASH(lp) rccEnableAHB2(RCC_AHB2ENR_HASHEN, lp) - -/** - * @brief Disables the HASH peripheral clock. - * - * @api - */ -#define rccDisableHASH() rccDisableAHB2(RCC_AHB2ENR_HASHEN) - -/** - * @brief Resets the HASH peripheral. - * - * @api - */ -#define rccResetHASH() rccResetAHB2(RCC_AHB2RSTR_HASHRST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1L(RCC_APB1LENR_DAC12EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1L(RCC_APB1LENR_DAC12EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1L(RCC_APB1LRSTR_DAC12RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the BDMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableBDMA1(lp) rccEnableAHB4(RCC_AHB4ENR_BDMAEN, lp) - -/** - * @brief Disables the BDMA1 peripheral clock. - * - * @api - */ -#define rccDisableBDMA1() rccDisableAHB4(RCC_AHB4ENR_BDMAEN) - -/** - * @brief Resets the BDMA1 peripheral. - * - * @api - */ -#define rccResetBDMA1() rccResetAHB4(RCC_AHB4RSTR_BDMARST) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) - -/** - * @brief Enables the MDMA peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableMDMA(lp) rccEnableAHB3(RCC_AHB3ENR_MDMAEN, lp) - -/** - * @brief Disables the MDMA peripheral clock. - * - * @api - */ -#define rccDisableMDMA() rccDisableAHB3(RCC_AHB3ENR_MDMAEN) - -/** - * @brief Resets the MDMA peripheral. - * - * @api - */ -#define rccResetMDMA() rccResetAHB3(RCC_AHB3ENR_MDMARST) -/** @} */ - -/** - * @name RAM specific RCC operations - * @{ - */ -/** - * @brief Enables the BKPRAM clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableBKPRAM(lp) rccEnableAHB4(RCC_AHB4ENR_BKPRAMEN, lp) - -/** - * @brief Disables the BKPRAM clock. - * - * @api - */ -#define rccDisableBKPRAM() rccDisableAHB4(RCC_AHB4ENR_BKPRAMEN) - -/** - * @brief Enables the SRAM1 clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSRAM1(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM1EN, lp) - -/** - * @brief Disables the SRAM1 clock. - * - * @api - */ -#define rccDisableSRAM1() rccDisableAHB2(RCC_AHB2ENR_D2SRAM1EN) - -/** - * @brief Enables the SRAM2 clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSRAM2(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM2EN, lp) - -/** - * @brief Disables the SRAM2 clock. - * - * @api - */ -#define rccDisableSRAM2() rccDisableAHB2(RCC_AHB2ENR_D2SRAM2EN) - -/** - * @brief Enables the SRAM3 clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSRAM3(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM3EN, lp) - -/** - * @brief Disables the SRAM3 clock. - * - * @api - */ -#define rccDisableSRAM3() rccDisableAHB2(RCC_AHB2ENR_D2SRAM3EN) -/** @} */ - -/** - * @name ETH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the ETH peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETH1MACEN | \ - RCC_AHB1ENR_ETH1TXEN | \ - RCC_AHB1ENR_ETH1RXEN, lp) - -/** - * @brief Disables the ETH peripheral clock. - * - * @api - */ -#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETH1MACEN | \ - RCC_AHB1ENR_ETH1TXEN | \ - RCC_AHB1ENR_ETH1RXEN) - -/** - * @brief Resets the ETH peripheral. - * - * @api - */ -#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETH1MACRST) -/** @} */ - -/** - * @name FDCAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FDCAN peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFDCAN(lp) rccEnableAPB1H(RCC_APB1HENR_FDCANEN, lp) - -/** - * @brief Disables the FDCAN peripheral clock. - * - * @api - */ -#define rccDisableFDCAN() rccDisableAPB1H(RCC_APB1HENR_FDCANEN) - -/** - * @brief Resets the FDCAN peripheral. - * - * @api - */ -#define rccResetFDCAN() rccResetAPB1H(RCC_APB1HRSTR_FDCANRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1L(RCC_APB1LENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1L(RCC_APB1LENR_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1L(RCC_APB1LRSTR_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1L(RCC_APB1LENR_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1L(RCC_APB1LENR_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1L(RCC_APB1LRSTR_I2C2RST) - -/** - * @brief Enables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C3(lp) rccEnableAPB1L(RCC_APB1LENR_I2C3EN, lp) - -/** - * @brief Disables the I2C3 peripheral clock. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1L(RCC_APB1LENR_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1L(RCC_APB1LRSTR_I2C3RST) - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C4(lp) rccEnableAPB4(RCC_APB4ENR_I2C4EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @api - */ -#define rccDisableI2C4() rccDisableAPB4(RCC_APB4ENR_I2C4EN) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB4(RCC_APB4RSTR_I2C4RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USB1_OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB1_OTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_USB1OTGHSEN, lp) - -/** - * @brief Disables the USB1_OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableUSB1_OTG_HS() rccDisableAHB1(RCC_AHB1ENR_USB1OTGHSEN) - -/** - * @brief Resets the USB1_OTG_HS peripheral. - * - * @api - */ -#define rccResetUSB1_OTG_HS() rccResetAHB1(RCC_AHB1RSTR_USB1OTGHSRST) - -/** - * @brief Enables the USB1_OTG_HS ULPI peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB1_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_USB1OTGHSULPIEN, lp) - -/** - * @brief Disables the USB1_OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableUSB1_HSULPI() rccDisableAHB1(RCC_AHB1ENR_USB1OTGHSULPIEN) - -/** - * @brief Enables the USB2_OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB2_OTG_FS(lp) rccEnableAHB1(RCC_AHB1ENR_USB2OTGFSEN, lp) - -/** - * @brief Disables the USB2_OTG_FS peripheral clock. - * - * @api - */ -#define rccDisableUSB2_OTG_FS() rccDisableAHB1(RCC_AHB1ENR_USB2OTGFSEN) - -/** - * @brief Resets the USB2_OTG_FS peripheral. - * - * @api - */ -#define rccResetUSB2_OTG_FS() rccResetAHB1(RCC_AHB1RSTR_USB2OTGFSRST) - -/** - * @brief Enables the USB2_OTG_HS ULPI peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB2_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_USB2OTGHSULPIEN, lp) - -/** - * @brief Disables the USB2_OTG_HS peripheral clock. - * - * @api - */ -#define rccDisableUSB2_HSULPI() rccDisableAHB1(RCC_AHB1ENR_USB2OTGHSULPIEN) -/** @} */ - -/** - * @name QUADSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the QUADSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) - -/** - * @brief Disables the QUADSPI1 peripheral clock. - * - * @api - */ -#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) - -/** - * @brief Resets the QUADSPI1 peripheral. - * - * @api - */ -#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) -/** @} */ - -/** - * @name SDMMC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDMMC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC1(lp) rccEnableAHB3(RCC_AHB3ENR_SDMMC1EN, lp) - -/** - * @brief Disables the SDMMC1 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC1() rccDisableAHB3(RCC_AHB3ENR_SDMMC1EN) - -/** - * @brief Resets the SDMMC1 peripheral. - * - * @api - */ -#define rccResetSDMMC1() rccResetAHB3(RCC_AHB3RSTR_SDMMC1RST) - -/** - * @brief Enables the SDMMC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC2(lp) rccEnableAHB2(RCC_AHB2ENR_SDMMC2EN, lp) - -/** - * @brief Disables the SDMMC2 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC2() rccDisableAHB2(RCC_AHB2ENR_SDMMC2EN) - -/** - * @brief Resets the SDMMC2 peripheral. - * - * @api - */ -#define rccResetSDMMC2() rccResetAHB2(RCC_AHB2RSTR_SDMMC2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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) rccEnableAPB1L(RCC_APB1LENR_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1L(RCC_APB1LENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1L(RCC_APB1LRSTR_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1L(RCC_APB1LENR_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1L(RCC_APB1LENR_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1L(RCC_APB1LRSTR_SPI3RST) - -/** - * @brief Enables the SPI4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) - -/** - * @brief Disables the SPI4 peripheral clock. - * - * @api - */ -#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) - -/** - * @brief Resets the SPI4 peripheral. - * - * @api - */ -#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) - -/** - * @brief Enables the SPI5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp) - -/** - * @brief Disables the SPI5 peripheral clock. - * - * @api - */ -#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN) - -/** - * @brief Resets the SPI5 peripheral. - * - * @api - */ -#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST) - -/** - * @brief Enables the SPI6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI6(lp) rccEnableAPB4(RCC_APB4ENR_SPI6EN, lp) - -/** - * @brief Disables the SPI6 peripheral clock. - * - * @api - */ -#define rccDisableSPI6() rccDisableAPB4(RCC_APB4ENR_SPI6EN) - -/** - * @brief Resets the SPI6 peripheral. - * - * @api - */ -#define rccResetSPI6() rccResetAPB4(RCC_APB4RSTR_SPI6RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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) rccEnableAPB1L(RCC_APB1LENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1L(RCC_APB1LENR_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1L(RCC_APB1LRSTR_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1L(RCC_APB1LENR_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1L(RCC_APB1LENR_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1L(RCC_APB1LRSTR_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1L(RCC_APB1LENR_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1L(RCC_APB1LENR_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1L(RCC_APB1LRSTR_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1L(RCC_APB1LENR_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1L(RCC_APB1LENR_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1L(RCC_APB1LRSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1L(RCC_APB1LENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1L(RCC_APB1LENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1L(RCC_APB1LRSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1L(RCC_APB1LENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1L(RCC_APB1LENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1L(RCC_APB1LRSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM12 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM12(lp) rccEnableAPB1L(RCC_APB1LENR_TIM12EN, lp) - -/** - * @brief Disables the TIM12 peripheral clock. - * - * @api - */ -#define rccDisableTIM12() rccDisableAPB1L(RCC_APB1LENR_TIM12EN) - -/** - * @brief Resets the TIM12 peripheral. - * - * @api - */ -#define rccResetTIM12() rccResetAPB1L(RCC_APB1LRSTR_TIM12RST) - -/** - * @brief Enables the TIM13 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM13(lp) rccEnableAPB1L(RCC_APB1LENR_TIM13EN, lp) - -/** - * @brief Disables the TIM13 peripheral clock. - * - * @api - */ -#define rccDisableTIM13() rccDisableAPB1L(RCC_APB1LENR_TIM13EN) - -/** - * @brief Resets the TIM13 peripheral. - * - * @api - */ -#define rccResetTIM13() rccResetAPB1L(RCC_APB1LRSTR_TIM13RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1L(RCC_APB1LENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * - * @api - */ -#define rccDisableTIM14() rccDisableAPB1L(RCC_APB1LENR_TIM14EN) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1L(RCC_APB1LRSTR_TIM14RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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) rccEnableAPB1L(RCC_APB1LENR_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1L(RCC_APB1LENR_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1L(RCC_APB1LRSTR_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1L(RCC_APB1LENR_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1L(RCC_APB1LENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1L(RCC_APB1LRSTR_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1L(RCC_APB1LENR_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1L(RCC_APB1LENR_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1L(RCC_APB1LRSTR_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1L(RCC_APB1LENR_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1L(RCC_APB1LENR_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1L(RCC_APB1LRSTR_UART5RST) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) - -/** - * @brief Resets the USART6 peripheral. - * - * @api - */ -#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) - -/** - * @brief Enables the UART7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART7(lp) rccEnableAPB1L(RCC_APB1LENR_UART7EN, lp) - -/** - * @brief Disables the UART7 peripheral clock. - * - * @api - */ -#define rccDisableUART7() rccDisableAPB1L(RCC_APB1LENR_UART7EN) - -/** - * @brief Resets the UART7 peripheral. - * - * @api - */ -#define rccResetUART7() rccResetAPB1L(RCC_APB1LRSTR_UART7RST) - -/** - * @brief Enables the UART8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART8(lp) rccEnableAPB1L(RCC_APB1LENR_UART8EN, lp) - -/** - * @brief Disables the UART8 peripheral clock. - * - * @api - */ -#define rccDisableUART8() rccDisableAPB1L(RCC_APB1LENR_UART8EN) - -/** - * @brief Resets the UART8 peripheral. - * - * @api - */ -#define rccResetUART8() rccResetAPB1L(RCC_APB1LRSTR_UART8RST) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPB4(RCC_APB4ENR_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPB4(RCC_APB4ENR_LPUART1EN) - -/** - * @brief Resets the LPUART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPB4(RCC_APB4RSTR_LPUART1RST) -/** @} */ - -/** - * @name LTDC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the LTDC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLTDC(lp) rccEnableAPB3(RCC_APB3ENR_LTDCEN, lp) - -/** - * @brief Disables the LTDC peripheral clock. -. * - * @api - */ -#define rccDisableLTDC() rccDisableAPB3(RCC_APB3ENR_LTDCEN) - -/** - * @brief Resets the LTDC peripheral. - * - * @api - */ -#define rccResetLTDC() rccResetAPB3(RCC_APB3RSTR_LTDCRST) - -/** - * @name DMA2D peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA2D peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2D(lp) rccEnableAHB3(RCC_AHB3ENR_DMA2DEN, lp) - -/** - * @brief Disables the DMA2D peripheral clock. - * - * @api - */ -#define rccDisableDMA2D() rccDisableAHB3(RCC_AHB3ENR_DMA2DEN) - -/** - * @brief Resets the DMA2D peripheral. - * - * @api - */ -#define rccResetDMA2D() rccResetAHB3(RCC_AHB3RSTR_DMA2DRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#if defined(STM32_FSMC_IS_FMC) - #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) -#else - #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp) -#endif - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#if defined(STM32_FSMC_IS_FMC) - #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) -#else - #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN) -#endif - -/** - * @brief Resets the FSMC peripheral. - * - * @api - */ -#if defined(STM32_FSMC_IS_FMC) - #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) -#else - #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST) -#endif -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F7xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f7xx.h. + * + * @addtogroup STM32F7xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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, low set + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1L(mask, lp) { \ + RCC->APB1LENR |= (mask); \ + if (lp) \ + RCC->APB1LLPENR |= (mask); \ + else \ + RCC->APB1LLPENR &= ~(mask); \ + (void)RCC->APB1LLPENR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask, high set + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1H(mask, lp) { \ + RCC->APB1HENR |= (mask); \ + if (lp) \ + RCC->APB1HLPENR |= (mask); \ + else \ + RCC->APB1HLPENR &= ~(mask); \ + (void)RCC->APB1HLPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask, low set + * + * @api + */ +#define rccDisableAPB1L(mask) { \ + RCC->APB1LENR &= ~(mask); \ + RCC->APB1LLPENR &= ~(mask); \ + (void)RCC->APB1LLPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask, high set + * + * @api + */ +#define rccDisableAPB1H(mask) { \ + RCC->APB1HENR &= ~(mask); \ + RCC->APB1HLPENR &= ~(mask); \ + (void)RCC->APB1HLPENR; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask, low set + * + * @api + */ +#define rccResetAPB1L(mask) { \ + RCC->APB1LRSTR |= (mask); \ + RCC->APB1LRSTR &= ~(mask); \ + (void)RCC->APB1LRSTR; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask, high set + * + * @api + */ +#define rccResetAPB1H(mask) { \ + RCC->APB1HRSTR |= (mask); \ + RCC->APB1HRSTR &= ~(mask); \ + (void)RCC->APB1HRSTR; \ +} + +/** + * @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); \ + else \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB3 bus. + * + * @param[in] mask APB3 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB3(mask, lp) { \ + RCC->APB3ENR |= (mask); \ + if (lp) \ + RCC->APB3LPENR |= (mask); \ + else \ + RCC->APB3LPENR &= ~(mask); \ + (void)RCC->APB3LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB3 bus. + * + * @param[in] mask APB3 peripherals mask + * + * @api + */ +#define rccDisableAPB3(mask) { \ + RCC->APB3ENR &= ~(mask); \ + RCC->APB3LPENR &= ~(mask); \ + (void)RCC->APB3LPENR; \ +} + +/** + * @brief Resets one or more peripheral on the APB3 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccResetAPB3(mask) { \ + RCC->APB3RSTR |= (mask); \ + RCC->APB3RSTR &= ~(mask); \ + (void)RCC->APB3RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB4 bus. + * + * @param[in] mask APB4 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB4(mask, lp) { \ + RCC->APB4ENR |= (mask); \ + if (lp) \ + RCC->APB4LPENR |= (mask); \ + else \ + RCC->APB4LPENR &= ~(mask); \ + (void)RCC->APB4LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB4 bus. + * + * @param[in] mask APB4 peripherals mask + * + * @api + */ +#define rccDisableAPB4(mask) { \ + RCC->APB4ENR &= ~(mask); \ + RCC->APB4LPENR &= ~(mask); \ + (void)RCC->APB4LPENR; \ +} + +/** + * @brief Resets one or more peripheral on the APB4 bus. + * + * @param[in] mask APB4 peripherals mask + * + * @api + */ +#define rccResetAPB4(mask) { \ + RCC->APB4RSTR |= (mask); \ + RCC->APB4RSTR &= ~(mask); \ + (void)RCC->APB4RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB1LPENR &= ~(mask); \ + (void)RCC->AHB1LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1LPENR &= ~(mask); \ + (void)RCC->AHB1LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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); \ + else \ + RCC->AHB2LPENR &= ~(mask); \ + (void)RCC->AHB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2LPENR &= ~(mask); \ + (void)RCC->AHB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB3 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); \ + else \ + RCC->AHB3LPENR &= ~(mask); \ + (void)RCC->AHB3LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3LPENR &= ~(mask); \ + (void)RCC->AHB3LPENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB3 bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccResetAHB3(mask) { \ + RCC->AHB3RSTR |= (mask); \ + RCC->AHB3RSTR &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB4 bus. + * + * @param[in] mask AHB4 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB4(mask, lp) { \ + RCC->AHB4ENR |= (mask); \ + if (lp) \ + RCC->AHB4LPENR |= (mask); \ + else \ + RCC->AHB4LPENR &= ~(mask); \ + (void)RCC->AHB4LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB4 bus. + * + * @param[in] mask AHB4 peripherals mask + * + * @api + */ +#define rccDisableAHB4(mask) { \ + RCC->AHB4ENR &= ~(mask); \ + RCC->AHB4LPENR &= ~(mask); \ + (void)RCC->AHB4LPENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB4 bus. + * + * @param[in] mask AHB4 peripherals mask + * + * @api + */ +#define rccResetAHB4(mask) { \ + RCC->AHB4RSTR |= (mask); \ + RCC->AHB4RSTR &= ~(mask); \ + (void)RCC->AHB4RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC12(lp) rccEnableAHB1(RCC_AHB1ENR_ADC12EN, lp) + +/** + * @brief Disables the ADC1/ADC2 peripheral clock. + * + * @api + */ +#define rccDisableADC12() rccDisableAHB1(RCC_AHB1ENR_ADC12EN) + +/** + * @brief Resets the ADC1/ADC2 peripheral. + * + * @api + */ +#define rccResetADC12() rccResetAHB1(RCC_AHB1RSTR_ADC12RST) + +/** + * @brief Enables the ADC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC3(lp) rccEnableAHB4(RCC_AHB4ENR_ADC3EN, lp) + +/** + * @brief Disables the ADC3 peripheral clock. + * + * @api + */ +#define rccDisableADC3() rccDisableAHB4(RCC_AHB4ENR_ADC3EN) + +/** + * @brief Resets the ADC3 peripheral. + * + * @api + */ +#define rccResetADC3() rccResetAHB4(RCC_AHB4RSTR_ADC3RST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB4(RCC_AHB4ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB4(RCC_AHB4ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB4(RCC_AHB4RSTR_CRCRST) +/** @} */ + +/** + * @name CRYP peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRYP peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRYP(lp) rccEnableAHB2(RCC_AHB2ENR_CRYPEN, lp) + +/** + * @brief Disables the CRYP peripheral clock. + * + * @api + */ +#define rccDisableCRYP() rccDisableAHB2(RCC_AHB2ENR_CRYPEN) + +/** + * @brief Resets the CRYP peripheral. + * + * @api + */ +#define rccResetCRYP() rccResetAHB2(RCC_AHB2RSTR_CRYPRST) +/** @} */ + +/** + * @name HASH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the HASH peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableHASH(lp) rccEnableAHB2(RCC_AHB2ENR_HASHEN, lp) + +/** + * @brief Disables the HASH peripheral clock. + * + * @api + */ +#define rccDisableHASH() rccDisableAHB2(RCC_AHB2ENR_HASHEN) + +/** + * @brief Resets the HASH peripheral. + * + * @api + */ +#define rccResetHASH() rccResetAHB2(RCC_AHB2RSTR_HASHRST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1L(RCC_APB1LENR_DAC12EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1L(RCC_APB1LENR_DAC12EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1L(RCC_APB1LRSTR_DAC12RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the BDMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableBDMA1(lp) rccEnableAHB4(RCC_AHB4ENR_BDMAEN, lp) + +/** + * @brief Disables the BDMA1 peripheral clock. + * + * @api + */ +#define rccDisableBDMA1() rccDisableAHB4(RCC_AHB4ENR_BDMAEN) + +/** + * @brief Resets the BDMA1 peripheral. + * + * @api + */ +#define rccResetBDMA1() rccResetAHB4(RCC_AHB4RSTR_BDMARST) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) + +/** + * @brief Enables the MDMA peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableMDMA(lp) rccEnableAHB3(RCC_AHB3ENR_MDMAEN, lp) + +/** + * @brief Disables the MDMA peripheral clock. + * + * @api + */ +#define rccDisableMDMA() rccDisableAHB3(RCC_AHB3ENR_MDMAEN) + +/** + * @brief Resets the MDMA peripheral. + * + * @api + */ +#define rccResetMDMA() rccResetAHB3(RCC_AHB3ENR_MDMARST) +/** @} */ + +/** + * @name RAM specific RCC operations + * @{ + */ +/** + * @brief Enables the BKPRAM clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableBKPRAM(lp) rccEnableAHB4(RCC_AHB4ENR_BKPRAMEN, lp) + +/** + * @brief Disables the BKPRAM clock. + * + * @api + */ +#define rccDisableBKPRAM() rccDisableAHB4(RCC_AHB4ENR_BKPRAMEN) + +/** + * @brief Enables the SRAM1 clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSRAM1(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM1EN, lp) + +/** + * @brief Disables the SRAM1 clock. + * + * @api + */ +#define rccDisableSRAM1() rccDisableAHB2(RCC_AHB2ENR_D2SRAM1EN) + +/** + * @brief Enables the SRAM2 clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSRAM2(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM2EN, lp) + +/** + * @brief Disables the SRAM2 clock. + * + * @api + */ +#define rccDisableSRAM2() rccDisableAHB2(RCC_AHB2ENR_D2SRAM2EN) + +/** + * @brief Enables the SRAM3 clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSRAM3(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM3EN, lp) + +/** + * @brief Disables the SRAM3 clock. + * + * @api + */ +#define rccDisableSRAM3() rccDisableAHB2(RCC_AHB2ENR_D2SRAM3EN) +/** @} */ + +/** + * @name ETH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the ETH peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETH1MACEN | \ + RCC_AHB1ENR_ETH1TXEN | \ + RCC_AHB1ENR_ETH1RXEN, lp) + +/** + * @brief Disables the ETH peripheral clock. + * + * @api + */ +#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETH1MACEN | \ + RCC_AHB1ENR_ETH1TXEN | \ + RCC_AHB1ENR_ETH1RXEN) + +/** + * @brief Resets the ETH peripheral. + * + * @api + */ +#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETH1MACRST) +/** @} */ + +/** + * @name FDCAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FDCAN peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFDCAN(lp) rccEnableAPB1H(RCC_APB1HENR_FDCANEN, lp) + +/** + * @brief Disables the FDCAN peripheral clock. + * + * @api + */ +#define rccDisableFDCAN() rccDisableAPB1H(RCC_APB1HENR_FDCANEN) + +/** + * @brief Resets the FDCAN peripheral. + * + * @api + */ +#define rccResetFDCAN() rccResetAPB1H(RCC_APB1HRSTR_FDCANRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1L(RCC_APB1LENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1L(RCC_APB1LENR_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1L(RCC_APB1LRSTR_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1L(RCC_APB1LENR_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1L(RCC_APB1LENR_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1L(RCC_APB1LRSTR_I2C2RST) + +/** + * @brief Enables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C3(lp) rccEnableAPB1L(RCC_APB1LENR_I2C3EN, lp) + +/** + * @brief Disables the I2C3 peripheral clock. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1L(RCC_APB1LENR_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1L(RCC_APB1LRSTR_I2C3RST) + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C4(lp) rccEnableAPB4(RCC_APB4ENR_I2C4EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @api + */ +#define rccDisableI2C4() rccDisableAPB4(RCC_APB4ENR_I2C4EN) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB4(RCC_APB4RSTR_I2C4RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USB1_OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB1_OTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_USB1OTGHSEN, lp) + +/** + * @brief Disables the USB1_OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableUSB1_OTG_HS() rccDisableAHB1(RCC_AHB1ENR_USB1OTGHSEN) + +/** + * @brief Resets the USB1_OTG_HS peripheral. + * + * @api + */ +#define rccResetUSB1_OTG_HS() rccResetAHB1(RCC_AHB1RSTR_USB1OTGHSRST) + +/** + * @brief Enables the USB1_OTG_HS ULPI peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB1_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_USB1OTGHSULPIEN, lp) + +/** + * @brief Disables the USB1_OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableUSB1_HSULPI() rccDisableAHB1(RCC_AHB1ENR_USB1OTGHSULPIEN) + +/** + * @brief Enables the USB2_OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB2_OTG_FS(lp) rccEnableAHB1(RCC_AHB1ENR_USB2OTGFSEN, lp) + +/** + * @brief Disables the USB2_OTG_FS peripheral clock. + * + * @api + */ +#define rccDisableUSB2_OTG_FS() rccDisableAHB1(RCC_AHB1ENR_USB2OTGFSEN) + +/** + * @brief Resets the USB2_OTG_FS peripheral. + * + * @api + */ +#define rccResetUSB2_OTG_FS() rccResetAHB1(RCC_AHB1RSTR_USB2OTGFSRST) + +/** + * @brief Enables the USB2_OTG_HS ULPI peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB2_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_USB2OTGHSULPIEN, lp) + +/** + * @brief Disables the USB2_OTG_HS peripheral clock. + * + * @api + */ +#define rccDisableUSB2_HSULPI() rccDisableAHB1(RCC_AHB1ENR_USB2OTGHSULPIEN) +/** @} */ + +/** + * @name QUADSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the QUADSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) + +/** + * @brief Disables the QUADSPI1 peripheral clock. + * + * @api + */ +#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) + +/** + * @brief Resets the QUADSPI1 peripheral. + * + * @api + */ +#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) +/** @} */ + +/** + * @name SDMMC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDMMC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC1(lp) rccEnableAHB3(RCC_AHB3ENR_SDMMC1EN, lp) + +/** + * @brief Disables the SDMMC1 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC1() rccDisableAHB3(RCC_AHB3ENR_SDMMC1EN) + +/** + * @brief Resets the SDMMC1 peripheral. + * + * @api + */ +#define rccResetSDMMC1() rccResetAHB3(RCC_AHB3RSTR_SDMMC1RST) + +/** + * @brief Enables the SDMMC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC2(lp) rccEnableAHB2(RCC_AHB2ENR_SDMMC2EN, lp) + +/** + * @brief Disables the SDMMC2 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC2() rccDisableAHB2(RCC_AHB2ENR_SDMMC2EN) + +/** + * @brief Resets the SDMMC2 peripheral. + * + * @api + */ +#define rccResetSDMMC2() rccResetAHB2(RCC_AHB2RSTR_SDMMC2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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) rccEnableAPB1L(RCC_APB1LENR_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1L(RCC_APB1LENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1L(RCC_APB1LRSTR_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1L(RCC_APB1LENR_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1L(RCC_APB1LENR_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1L(RCC_APB1LRSTR_SPI3RST) + +/** + * @brief Enables the SPI4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp) + +/** + * @brief Disables the SPI4 peripheral clock. + * + * @api + */ +#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN) + +/** + * @brief Resets the SPI4 peripheral. + * + * @api + */ +#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST) + +/** + * @brief Enables the SPI5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp) + +/** + * @brief Disables the SPI5 peripheral clock. + * + * @api + */ +#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN) + +/** + * @brief Resets the SPI5 peripheral. + * + * @api + */ +#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST) + +/** + * @brief Enables the SPI6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI6(lp) rccEnableAPB4(RCC_APB4ENR_SPI6EN, lp) + +/** + * @brief Disables the SPI6 peripheral clock. + * + * @api + */ +#define rccDisableSPI6() rccDisableAPB4(RCC_APB4ENR_SPI6EN) + +/** + * @brief Resets the SPI6 peripheral. + * + * @api + */ +#define rccResetSPI6() rccResetAPB4(RCC_APB4RSTR_SPI6RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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) rccEnableAPB1L(RCC_APB1LENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1L(RCC_APB1LENR_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1L(RCC_APB1LRSTR_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1L(RCC_APB1LENR_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1L(RCC_APB1LENR_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1L(RCC_APB1LRSTR_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1L(RCC_APB1LENR_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1L(RCC_APB1LENR_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1L(RCC_APB1LRSTR_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1L(RCC_APB1LENR_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1L(RCC_APB1LENR_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1L(RCC_APB1LRSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1L(RCC_APB1LENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1L(RCC_APB1LENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1L(RCC_APB1LRSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1L(RCC_APB1LENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1L(RCC_APB1LENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1L(RCC_APB1LRSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM12 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM12(lp) rccEnableAPB1L(RCC_APB1LENR_TIM12EN, lp) + +/** + * @brief Disables the TIM12 peripheral clock. + * + * @api + */ +#define rccDisableTIM12() rccDisableAPB1L(RCC_APB1LENR_TIM12EN) + +/** + * @brief Resets the TIM12 peripheral. + * + * @api + */ +#define rccResetTIM12() rccResetAPB1L(RCC_APB1LRSTR_TIM12RST) + +/** + * @brief Enables the TIM13 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM13(lp) rccEnableAPB1L(RCC_APB1LENR_TIM13EN, lp) + +/** + * @brief Disables the TIM13 peripheral clock. + * + * @api + */ +#define rccDisableTIM13() rccDisableAPB1L(RCC_APB1LENR_TIM13EN) + +/** + * @brief Resets the TIM13 peripheral. + * + * @api + */ +#define rccResetTIM13() rccResetAPB1L(RCC_APB1LRSTR_TIM13RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1L(RCC_APB1LENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * + * @api + */ +#define rccDisableTIM14() rccDisableAPB1L(RCC_APB1LENR_TIM14EN) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1L(RCC_APB1LRSTR_TIM14RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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) rccEnableAPB1L(RCC_APB1LENR_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1L(RCC_APB1LENR_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1L(RCC_APB1LRSTR_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1L(RCC_APB1LENR_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1L(RCC_APB1LENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1L(RCC_APB1LRSTR_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1L(RCC_APB1LENR_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1L(RCC_APB1LENR_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1L(RCC_APB1LRSTR_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1L(RCC_APB1LENR_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1L(RCC_APB1LENR_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1L(RCC_APB1LRSTR_UART5RST) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN) + +/** + * @brief Resets the USART6 peripheral. + * + * @api + */ +#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) + +/** + * @brief Enables the UART7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART7(lp) rccEnableAPB1L(RCC_APB1LENR_UART7EN, lp) + +/** + * @brief Disables the UART7 peripheral clock. + * + * @api + */ +#define rccDisableUART7() rccDisableAPB1L(RCC_APB1LENR_UART7EN) + +/** + * @brief Resets the UART7 peripheral. + * + * @api + */ +#define rccResetUART7() rccResetAPB1L(RCC_APB1LRSTR_UART7RST) + +/** + * @brief Enables the UART8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART8(lp) rccEnableAPB1L(RCC_APB1LENR_UART8EN, lp) + +/** + * @brief Disables the UART8 peripheral clock. + * + * @api + */ +#define rccDisableUART8() rccDisableAPB1L(RCC_APB1LENR_UART8EN) + +/** + * @brief Resets the UART8 peripheral. + * + * @api + */ +#define rccResetUART8() rccResetAPB1L(RCC_APB1LRSTR_UART8RST) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPB4(RCC_APB4ENR_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPB4(RCC_APB4ENR_LPUART1EN) + +/** + * @brief Resets the LPUART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPB4(RCC_APB4RSTR_LPUART1RST) +/** @} */ + +/** + * @name LTDC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the LTDC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLTDC(lp) rccEnableAPB3(RCC_APB3ENR_LTDCEN, lp) + +/** + * @brief Disables the LTDC peripheral clock. +. * + * @api + */ +#define rccDisableLTDC() rccDisableAPB3(RCC_APB3ENR_LTDCEN) + +/** + * @brief Resets the LTDC peripheral. + * + * @api + */ +#define rccResetLTDC() rccResetAPB3(RCC_APB3RSTR_LTDCRST) + +/** + * @name DMA2D peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA2D peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2D(lp) rccEnableAHB3(RCC_AHB3ENR_DMA2DEN, lp) + +/** + * @brief Disables the DMA2D peripheral clock. + * + * @api + */ +#define rccDisableDMA2D() rccDisableAHB3(RCC_AHB3ENR_DMA2DEN) + +/** + * @brief Resets the DMA2D peripheral. + * + * @api + */ +#define rccResetDMA2D() rccResetAHB3(RCC_AHB3RSTR_DMA2DRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#if defined(STM32_FSMC_IS_FMC) + #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) +#else + #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp) +#endif + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#if defined(STM32_FSMC_IS_FMC) + #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) +#else + #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN) +#endif + +/** + * @brief Resets the FSMC peripheral. + * + * @api + */ +#if defined(STM32_FSMC_IS_FMC) + #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) +#else + #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST) +#endif +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_registry.h b/os/hal/ports/STM32/STM32H7xx/stm32_registry.h index f102679ced..1e7e7e2428 100644 --- a/os/hal/ports/STM32/STM32H7xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32H7xx/stm32_registry.h @@ -1,558 +1,558 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32H7xx/stm32_registry.h - * @brief STM32H7xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/* Cores.*/ -#if defined(STM32H750xx) || defined(STM32H742xx) || \ - defined(STM32H743xx) || defined(STM32H753xx) -#define STM32_HAS_M7 TRUE -#define STM32_HAS_M4 FALSE -#else -#define STM32_HAS_M7 TRUE -#define STM32_HAS_M4 TRUE -#endif - -/** - * @name STM32H7xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* I2C attributes.*/ -#define STM32_I2C4_USE_BDMA TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 128 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 18 -#define STM32_RTC_WKUP_EXTI 19 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ -} while (false) - -/*===========================================================================*/ -/* STM32H730xx, STM32H750xx, STM32H7B0xx, STM32H733xx, STM32H735xx, */ -/* STM32H753xx, STM32H7B3xx, STM32H755xx, STM32H757xx */ -/*===========================================================================*/ - -#if defined(STM32H730xx) || defined(STM32H750xx) || \ - defined(STM32H7B0xx) || defined(STM32H733xx) || \ - defined(STM32H735xx) || defined(STM32H753xx) || \ - defined(STM32H7B3xx) || defined(STM32H755xx) || \ - defined(STM32H757xx) || \ - defined(__DOXYGEN__) - -/* HASH attributes.*/ -#define STM32_HAS_HASH1 TRUE - -/* CRYP attributes.*/ -#define STM32_HAS_CRYP1 TRUE - -#else - -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE - -#endif - -/*===========================================================================*/ -/* STM32H743xx, STM32H753xx, STM32H745xx, STM32H755xx, STM32H747xx, */ -/* STM32H757xx. */ -/*===========================================================================*/ -#if defined(STM32H743xx) || defined(STM32H753xx) || \ - defined(STM32H745xx) || defined(STM32H755xx) || \ - defined(STM32H747xx) || defined(STM32H757xx) || \ - defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 TRUE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_FDCAN1 TRUE -#define STM32_HAS_FDCAN2 TRUE -#define STM32_HAS_FDCAN3 FALSE -#define STM32_FDCAN_FLS_NBR 64U -#define STM32_FDCAN_FLE_NBR 64U -#define STM32_FDCAN_RF0_NBR 48U -#define STM32_FDCAN_RF1_NBR 48U -#define STM32_FDCAN_RB_NBR 0U -#define STM32_FDCAN_TEF_NBR 0U -#define STM32_FDCAN_TB_NBR 32U -#define STM32_FDCAN_TM_NBR 0U - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* BDMA attributes.*/ -#define STM32_HAS_BDMA1 TRUE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE - -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* MDMA attributes.*/ -#define STM32_HAS_MDMA1 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE - -/* EXTI attributes.*/ -#define STM32_EXTI_ENHANCED -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ TRUE -#define STM32_HAS_GPIOK TRUE -#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \ - RCC_AHB4ENR_GPIOBEN | \ - RCC_AHB4ENR_GPIOCEN | \ - RCC_AHB4ENR_GPIODEN | \ - RCC_AHB4ENR_GPIOEEN | \ - RCC_AHB4ENR_GPIOFEN | \ - RCC_AHB4ENR_GPIOGEN | \ - RCC_AHB4ENR_GPIOHEN | \ - RCC_AHB4ENR_GPIOIEN | \ - RCC_AHB4ENR_GPIOJEN | \ - RCC_AHB4ENR_GPIOKEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 TRUE -#define STM32_HAS_I2C4 TRUE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_HAS_QUADSPI2 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_HAS_SDMMC2 TRUE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI6 TRUE -#define STM32_SPI6_SUPPORTS_I2S FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 FALSE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 FALSE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_UART5 TRUE -#define STM32_HAS_USART6 TRUE -#define STM32_HAS_UART7 TRUE -#define STM32_HAS_UART8 TRUE -#define STM32_HAS_LPUART1 TRUE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 8 - -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 8 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI TRUE - -#endif /* defined(STM32H743xx) || defined(STM32H753xx) */ -/** @} */ - -/*===========================================================================*/ -/* STM32H750xx. */ -/*===========================================================================*/ -#if defined(STM32H750xx) || \ - defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_FDCAN1 TRUE -#define STM32_HAS_FDCAN2 TRUE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* BDMA attributes.*/ -#define STM32_HAS_BDMA1 TRUE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE - -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* MDMA attributes.*/ -#define STM32_HAS_MDMA1 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE - -/* EXTI attributes.*/ -#define STM32_EXTI_ENHANCED -#define STM32_EXTI_NUM_LINES 34 -#define STM32_EXTI_IMR1_MASK 0x1F800000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ TRUE -#define STM32_HAS_GPIOK TRUE -#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \ - RCC_AHB4ENR_GPIOBEN | \ - RCC_AHB4ENR_GPIOCEN | \ - RCC_AHB4ENR_GPIODEN | \ - RCC_AHB4ENR_GPIOEEN | \ - RCC_AHB4ENR_GPIOFEN | \ - RCC_AHB4ENR_GPIOGEN | \ - RCC_AHB4ENR_GPIOHEN | \ - RCC_AHB4ENR_GPIOIEN | \ - RCC_AHB4ENR_GPIOJEN | \ - RCC_AHB4ENR_GPIOKEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 TRUE -#define STM32_HAS_I2C4 TRUE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_HAS_QUADSPI2 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_HAS_SDMMC2 TRUE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S TRUE -#define STM32_SPI1_I2S_FULLDUPLEX TRUE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX TRUE - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX TRUE - -#define STM32_HAS_SPI4 TRUE -#define STM32_SPI4_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI5 TRUE -#define STM32_SPI5_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI6 TRUE -#define STM32_SPI6_SUPPORTS_I2S FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 1 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 FALSE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 FALSE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 1 - -#define STM32_HAS_TIM17 FALSE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 1 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_UART5 TRUE -#define STM32_HAS_USART6 TRUE -#define STM32_HAS_UART7 TRUE -#define STM32_HAS_UART8 TRUE -#define STM32_HAS_LPUART1 TRUE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 8 - -#define STM32_HAS_OTG2 TRUE -#define STM32_OTG2_ENDPOINTS 8 - -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI TRUE - -#endif /* defined(STM32H750xx) */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32H7xx/stm32_registry.h + * @brief STM32H7xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/* Cores.*/ +#if defined(STM32H750xx) || defined(STM32H742xx) || \ + defined(STM32H743xx) || defined(STM32H753xx) +#define STM32_HAS_M7 TRUE +#define STM32_HAS_M4 FALSE +#else +#define STM32_HAS_M7 TRUE +#define STM32_HAS_M4 TRUE +#endif + +/** + * @name STM32H7xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* I2C attributes.*/ +#define STM32_I2C4_USE_BDMA TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 18 +#define STM32_RTC_WKUP_EXTI 19 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI17_PRIORITY); \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ +} while (false) + +/*===========================================================================*/ +/* STM32H730xx, STM32H750xx, STM32H7B0xx, STM32H733xx, STM32H735xx, */ +/* STM32H753xx, STM32H7B3xx, STM32H755xx, STM32H757xx */ +/*===========================================================================*/ + +#if defined(STM32H730xx) || defined(STM32H750xx) || \ + defined(STM32H7B0xx) || defined(STM32H733xx) || \ + defined(STM32H735xx) || defined(STM32H753xx) || \ + defined(STM32H7B3xx) || defined(STM32H755xx) || \ + defined(STM32H757xx) || \ + defined(__DOXYGEN__) + +/* HASH attributes.*/ +#define STM32_HAS_HASH1 TRUE + +/* CRYP attributes.*/ +#define STM32_HAS_CRYP1 TRUE + +#else + +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE + +#endif + +/*===========================================================================*/ +/* STM32H743xx, STM32H753xx, STM32H745xx, STM32H755xx, STM32H747xx, */ +/* STM32H757xx. */ +/*===========================================================================*/ +#if defined(STM32H743xx) || defined(STM32H753xx) || \ + defined(STM32H745xx) || defined(STM32H755xx) || \ + defined(STM32H747xx) || defined(STM32H757xx) || \ + defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 TRUE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_FDCAN1 TRUE +#define STM32_HAS_FDCAN2 TRUE +#define STM32_HAS_FDCAN3 FALSE +#define STM32_FDCAN_FLS_NBR 64U +#define STM32_FDCAN_FLE_NBR 64U +#define STM32_FDCAN_RF0_NBR 48U +#define STM32_FDCAN_RF1_NBR 48U +#define STM32_FDCAN_RB_NBR 0U +#define STM32_FDCAN_TEF_NBR 0U +#define STM32_FDCAN_TB_NBR 32U +#define STM32_FDCAN_TM_NBR 0U + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* BDMA attributes.*/ +#define STM32_HAS_BDMA1 TRUE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE + +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* MDMA attributes.*/ +#define STM32_HAS_MDMA1 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE + +/* EXTI attributes.*/ +#define STM32_EXTI_ENHANCED +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ TRUE +#define STM32_HAS_GPIOK TRUE +#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \ + RCC_AHB4ENR_GPIOBEN | \ + RCC_AHB4ENR_GPIOCEN | \ + RCC_AHB4ENR_GPIODEN | \ + RCC_AHB4ENR_GPIOEEN | \ + RCC_AHB4ENR_GPIOFEN | \ + RCC_AHB4ENR_GPIOGEN | \ + RCC_AHB4ENR_GPIOHEN | \ + RCC_AHB4ENR_GPIOIEN | \ + RCC_AHB4ENR_GPIOJEN | \ + RCC_AHB4ENR_GPIOKEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 TRUE +#define STM32_HAS_I2C4 TRUE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_HAS_QUADSPI2 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_HAS_SDMMC2 TRUE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI6 TRUE +#define STM32_SPI6_SUPPORTS_I2S FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 FALSE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 FALSE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_UART5 TRUE +#define STM32_HAS_USART6 TRUE +#define STM32_HAS_UART7 TRUE +#define STM32_HAS_UART8 TRUE +#define STM32_HAS_LPUART1 TRUE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 8 + +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 8 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI TRUE + +#endif /* defined(STM32H743xx) || defined(STM32H753xx) */ +/** @} */ + +/*===========================================================================*/ +/* STM32H750xx. */ +/*===========================================================================*/ +#if defined(STM32H750xx) || \ + defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_FDCAN1 TRUE +#define STM32_HAS_FDCAN2 TRUE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* BDMA attributes.*/ +#define STM32_HAS_BDMA1 TRUE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE + +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* MDMA attributes.*/ +#define STM32_HAS_MDMA1 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE + +/* EXTI attributes.*/ +#define STM32_EXTI_ENHANCED +#define STM32_EXTI_NUM_LINES 34 +#define STM32_EXTI_IMR1_MASK 0x1F800000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ TRUE +#define STM32_HAS_GPIOK TRUE +#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \ + RCC_AHB4ENR_GPIOBEN | \ + RCC_AHB4ENR_GPIOCEN | \ + RCC_AHB4ENR_GPIODEN | \ + RCC_AHB4ENR_GPIOEEN | \ + RCC_AHB4ENR_GPIOFEN | \ + RCC_AHB4ENR_GPIOGEN | \ + RCC_AHB4ENR_GPIOHEN | \ + RCC_AHB4ENR_GPIOIEN | \ + RCC_AHB4ENR_GPIOJEN | \ + RCC_AHB4ENR_GPIOKEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 TRUE +#define STM32_HAS_I2C4 TRUE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_HAS_QUADSPI2 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_HAS_SDMMC2 TRUE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S TRUE +#define STM32_SPI1_I2S_FULLDUPLEX TRUE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX TRUE + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX TRUE + +#define STM32_HAS_SPI4 TRUE +#define STM32_SPI4_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI5 TRUE +#define STM32_SPI5_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI6 TRUE +#define STM32_SPI6_SUPPORTS_I2S FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 1 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 FALSE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 FALSE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 1 + +#define STM32_HAS_TIM17 FALSE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 1 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_UART5 TRUE +#define STM32_HAS_USART6 TRUE +#define STM32_HAS_UART7 TRUE +#define STM32_HAS_UART8 TRUE +#define STM32_HAS_LPUART1 TRUE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 8 + +#define STM32_HAS_OTG2 TRUE +#define STM32_OTG2_ENDPOINTS 8 + +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI TRUE + +#endif /* defined(STM32H750xx) */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L0xx/hal_lld.c b/os/hal/ports/STM32/STM32L0xx/hal_lld.c index 43ab11bf96..d26f261cfc 100644 --- a/os/hal/ports/STM32/STM32L0xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32L0xx/hal_lld.c @@ -1,269 +1,270 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L0xx/hal_lld.c - * @brief STM32L0xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32l0xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->CSR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->CSR |= RCC_CSR_RTCRST; - RCC->CSR &= ~RCC_CSR_RTCRST; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - RCC->CSR |= RCC_CSR_LSEON; - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->CSR & RCC_CSR_LSERDY) == 0) - ; -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->CSR & RCC_CSR_RTCEN) == 0) { - /* Selects clock source.*/ - RCC->CSR |= STM32_RTCSEL; -#if STM32_LSE_ENABLED - RCC->CSR |= (RCC->CSR & RCC_CSR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->CSR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->CSR |= RCC_CSR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals except those on IOP.*/ - rccResetAHB(~RCC_AHBRSTR_MIFRST); - rccResetAPB1(~RCC_APB1RSTR_PWRRST); - rccResetAPB2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32L0xx voltage, clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -/** - * @brief Clocks and internal voltage initialization. - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ - RCC->APB1ENR = RCC_APB1ENR_PWREN; - - /* Core voltage setup.*/ - while ((PWR->CSR & PWR_CSR_VOSF) != 0) - ; /* Waits until regulator is stable. */ - PWR->CR = STM32_VOS; - while ((PWR->CSR & PWR_CSR_VOSF) != 0) - ; /* Waits until regulator is stable. */ - - /* Initial clocks setup and wait for MSI stabilization, the MSI clock is - always enabled because it is the fallback clock when PLL the fails. - Trim fields are not altered from reset values.*/ - RCC->CFGR = 0; - RCC->ICSCR = (RCC->ICSCR & ~STM32_MSIRANGE_MASK) | STM32_MSIRANGE; - RCC->CR = RCC_CR_MSION; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; /* Waits until MSI is stable. */ - -#if STM32_HSI16_ENABLED - /* HSI activation.*/ - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Waits until HSI16 is stable. */ - -#if STM32_HSI16_DIVIDER_ENABLED - RCC->CR |= RCC_CR_HSIDIVEN; - while ((RCC->CR & RCC_CR_HSIDIVF) == 0) - ; -#endif -#endif - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - -#if STM32_LSE_ENABLED - /* LSE activation, have to unlock the register.*/ - if ((RCC->CSR & RCC_CSR_LSEON) == 0) { - PWR->CR |= PWR_CR_DBP; -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->CSR |= STM32_LSEDRV | RCC_CSR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->CSR |= STM32_LSEDRV; -#endif - RCC->CSR |= RCC_CSR_LSEON; - PWR->CR &= ~PWR_CR_DBP; - } - while ((RCC->CSR & RCC_CSR_LSERDY) == 0) - ; /* Waits until LSE is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CFGR |= STM32_PLLDIV | STM32_PLLMUL | STM32_PLLSRC; - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - -#if STM32_ACTIVATE_HSI48 - /* Enabling SYSCFG clock. */ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); - /* Configuring SYSCFG to enable VREFINT and HSI48 VREFINT buffer. */ - SYSCFG->CFGR3 = STM32_VREFINT_EN | SYSCFG_CFGR3_ENREF_HSI48; - - while (!(SYSCFG->CFGR3 & SYSCFG_CFGR3_VREFINT_RDYF)) - ; /* Waits until VREFINT is stable. */ - /* Disabling SYSCFG clock. */ - rccDisableAPB2(RCC_APB2ENR_SYSCFGEN); - - /* Enabling HSI48. */ - RCC->CRRCR |= RCC_CRRCR_HSI48ON; - while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) - ; /* Waits until HSI48 is stable. */ -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CR |= STM32_RTCPRE; - RCC->CFGR |= STM32_MCOPRE | STM32_MCOSEL | - STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - RCC->CSR |= STM32_RTCSEL; - - /* Flash setup and final clock selection.*/ -#if defined(STM32_FLASHBITS) - FLASH->ACR = STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } -#endif - - /* Switching to the configured clock source if it is different from MSI. */ -#if (STM32_SW != STM32_SW_MSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif - - /* Peripherals clock sources setup.*/ - RCC->CCIPR = STM32_HSI48SEL | STM32_LPTIM1SEL | STM32_I2C1SEL | - STM32_LPUART1SEL | STM32_USART2SEL | STM32_USART1SEL; - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -#endif /* STM32_NO_INIT */ -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L0xx/hal_lld.c + * @brief STM32L0xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32l0xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->CSR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->CSR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->CSR |= RCC_CSR_RTCRST; + RCC->CSR &= ~RCC_CSR_RTCRST; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; + RCC->CSR |= RCC_CSR_LSEON; + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->CSR & RCC_CSR_LSERDY) == 0) + ; +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->CSR & RCC_CSR_RTCEN) == 0) { + /* Selects clock source.*/ + RCC->CSR |= STM32_RTCSEL; +#if STM32_LSE_ENABLED + RCC->CSR |= (RCC->CSR & RCC_CSR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->CSR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->CSR |= RCC_CSR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals except those on IOP.*/ + rccResetAHB(~RCC_AHBRSTR_MIFRST); + rccResetAPB1(~RCC_APB1RSTR_PWRRST); + rccResetAPB2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32L0xx voltage, clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +/** + * @brief Clocks and internal voltage initialization. + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ + RCC->APB1ENR = RCC_APB1ENR_PWREN; + + /* Core voltage setup.*/ + while ((PWR->CSR & PWR_CSR_VOSF) != 0) + ; /* Waits until regulator is stable. */ + PWR->CR = STM32_VOS; + while ((PWR->CSR & PWR_CSR_VOSF) != 0) + ; /* Waits until regulator is stable. */ + + /* Initial clocks setup and wait for MSI stabilization, the MSI clock is + always enabled because it is the fallback clock when PLL the fails. + Trim fields are not altered from reset values.*/ + RCC->CFGR = 0; + RCC->ICSCR = (RCC->ICSCR & ~STM32_MSIRANGE_MASK) | STM32_MSIRANGE; + RCC->CR = RCC_CR_MSION; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; /* Waits until MSI is stable. */ + +#if STM32_HSI16_ENABLED + /* HSI activation.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Waits until HSI16 is stable. */ + +#if STM32_HSI16_DIVIDER_ENABLED + RCC->CR |= RCC_CR_HSIDIVEN; + while ((RCC->CR & RCC_CR_HSIDIVF) == 0) + ; +#endif +#endif + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + +#if STM32_LSE_ENABLED + /* LSE activation, have to unlock the register.*/ + if ((RCC->CSR & RCC_CSR_LSEON) == 0) { + PWR->CR |= PWR_CR_DBP; +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->CSR |= STM32_LSEDRV | RCC_CSR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->CSR |= STM32_LSEDRV; +#endif + RCC->CSR |= RCC_CSR_LSEON; + PWR->CR &= ~PWR_CR_DBP; + } + while ((RCC->CSR & RCC_CSR_LSERDY) == 0) + ; /* Waits until LSE is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CFGR |= STM32_PLLDIV | STM32_PLLMUL | STM32_PLLSRC; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + +#if STM32_ACTIVATE_HSI48 + /* Enabling SYSCFG clock. */ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); + /* Configuring SYSCFG to enable VREFINT and HSI48 VREFINT buffer. */ + SYSCFG->CFGR3 = STM32_VREFINT_EN | SYSCFG_CFGR3_ENREF_HSI48; + + while (!(SYSCFG->CFGR3 & SYSCFG_CFGR3_VREFINT_RDYF)) + ; /* Waits until VREFINT is stable. */ + /* Disabling SYSCFG clock. */ + rccDisableAPB2(RCC_APB2ENR_SYSCFGEN); + + /* Enabling HSI48. */ + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) + ; /* Waits until HSI48 is stable. */ +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CR |= STM32_RTCPRE; + RCC->CFGR |= STM32_MCOPRE | STM32_MCOSEL | + STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + RCC->CSR |= STM32_RTCSEL; + + /* Flash setup and final clock selection.*/ +#if defined(STM32_FLASHBITS) + FLASH->ACR = STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } +#endif + + /* Switching to the configured clock source if it is different from MSI. */ +#if (STM32_SW != STM32_SW_MSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif + + /* Peripherals clock sources setup.*/ + RCC->CCIPR = STM32_HSI48SEL | STM32_LPTIM1SEL | STM32_I2C1SEL | + STM32_LPUART1SEL | STM32_USART2SEL | STM32_USART1SEL; + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +#endif /* STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L0xx/hal_lld.h b/os/hal/ports/STM32/STM32L0xx/hal_lld.h index 0c89bd0135..15307f0b35 100644 --- a/os/hal/ports/STM32/STM32L0xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32L0xx/hal_lld.h @@ -1,1253 +1,1262 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L0xx/hal_lld.h - * @brief STM32L0xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32L011xx, STM32L031xx, - * STM32L051xx, STM32L052xx, STM32L053xx, - * STM32L061xx, STM32L062xx, STM32L063xx, - * STM32L071xx, STM32L072xx, STM32L073xx for ultra-low-power MCUs. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -/* - * Registry definitions. - */ -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification macros - * @{ - */ -#if defined(STM32L011xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32L011xx ultra-low-power MCU" - -#elif defined(STM32L031xx) -#define PLATFORM_NAME "STM32L031xx ultra-low-power MCU" - -#elif defined(STM32L051xx) -#define PLATFORM_NAME "STM32L051xx ultra-low-power MCU" - -#elif defined(STM32L052xx) -#define PLATFORM_NAME "STM32L052xx ultra-low-power MCU" - -#elif defined(STM32L053xx) -#define PLATFORM_NAME "STM32L053xx ultra-low-power MCU" - -#elif defined(STM32L061xx) -#define PLATFORM_NAME "STM32L061xx ultra-low-power MCU" - -#elif defined(STM32L062xx) -#define PLATFORM_NAME "STM32L062xx ultra-low-power MCU" - -#elif defined(STM32L063xx) -#define PLATFORM_NAME "STM32L063xx ultra-low-power MCU" - -#elif defined(STM32L071xx) -#define PLATFORM_NAME "STM32L071xx ultra-low-power MCU" - -#elif defined(STM32L072xx) -#define PLATFORM_NAME "STM32L073xx ultra-low-power MCU" - -#elif defined(STM32L073xx) -#define PLATFORM_NAME "STM32L073xx ultra-low-power MCU" - -#else -#error "STM32L0xx device not specified" -#endif -/** @} */ - -/** - * @name Sub-family identifier - */ -#if !defined(STM32L0XX) || defined(__DOXYGEN__) -#define STM32L0XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ -#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ -#define STM32_LSICLK 37000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 5) /**< PLS field mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_EXT (7 << 5) /**< PVD level 7. */ - -#define STM32_VOS_MASK (3 << 11) /**< VOS field mask. */ -#define STM32_VOS_1P8 (1 << 11) /**< VOS level 1.8 volts. */ -#define STM32_VOS_1P5 (2 << 11) /**< VOS level 1.5 volts. */ -#define STM32_VOS_1P2 (3 << 11) /**< VOS level 1.2 volts. */ -/** @} */ - -/** - * @name RCC_CR register bits definitions - * @{ - */ -#define STM32_RTCPRE_MASK (3 << 20) /**< RTCPRE mask. */ -#define STM32_RTCPRE_DIV2 (0 << 20) /**< HSE divided by 2. */ -#define STM32_RTCPRE_DIV4 (1 << 20) /**< HSE divided by 4. */ -#define STM32_RTCPRE_DIV8 (2 << 20) /**< HSE divided by 2. */ -#define STM32_RTCPRE_DIV16 (3 << 20) /**< HSE divided by 16. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ -#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ -#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI16 */ -#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 8) /**< PPRE2 field mask. */ -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_STOPWUCK_MASK (1 << 15) /**< PLLDIV field mask. */ -#define STM32_STOPWUCK_MSI (0 << 15) /**< MSI is wakeup clock. */ -#define STM32_STOPWUCK_HSI16 (1 << 15) /**< HSI16 is wakeup clock. */ - -#define STM32_PLLSRC_MASK (1 << 16) /**< PLLSRC field mask. */ -#define STM32_PLLSRC_HSI16 (0 << 16) /**< PLL clock source is HSI16. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ - -#define STM32_PLLMUL_MASK (15 << 18) /**< PLLMUL field mask. */ -#define STM32_PLLMUL_MUL3 (0 << 18) /**< PLL multiplier is 3. */ -#define STM32_PLLMUL_MUL4 (1 << 18) /**< PLL multiplier is 4. */ -#define STM32_PLLMUL_MUL6 (2 << 18) /**< PLL multiplier is 6. */ -#define STM32_PLLMUL_MUL8 (3 << 18) /**< PLL multiplier is 8. */ -#define STM32_PLLMUL_MUL12 (4 << 18) /**< PLL multiplier is 12. */ -#define STM32_PLLMUL_MUL16 (5 << 18) /**< PLL multiplier is 16. */ -#define STM32_PLLMUL_MUL24 (6 << 18) /**< PLL multiplier is 24. */ -#define STM32_PLLMUL_MUL32 (7 << 18) /**< PLL multiplier is 32. */ -#define STM32_PLLMUL_MUL48 (8 << 18) /**< PLL multiplier is 48. */ - -#define STM32_PLLDIV_MASK (3 << 22) /**< PLLDIV field mask. */ -#define STM32_PLLDIV_DIV2 (1 << 22) /**< PLL divided by 2. */ -#define STM32_PLLDIV_DIV3 (2 << 22) /**< PLL divided by 3. */ -#define STM32_PLLDIV_DIV4 (3 << 22) /**< PLL divided by 4. */ - -#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI16 (2 << 24) /**< HSI16 clock on MCO pin. */ -#define STM32_MCOSEL_MSI (3 << 24) /**< MSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ - -#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ -#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO is divided by 1. */ -#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO is divided by 1. */ -#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO is divided by 1. */ -#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO is divided by 1. */ -#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO is divided by 1. */ -/** @} */ - -/** - * @name RCC_ICSCR register bits definitions - * @{ - */ -#define STM32_MSIRANGE_MASK (7 << 13) /**< MSIRANGE field mask. */ -#define STM32_MSIRANGE_64K (0 << 13) /**< 64kHz nominal. */ -#define STM32_MSIRANGE_128K (1 << 13) /**< 128kHz nominal. */ -#define STM32_MSIRANGE_256K (2 << 13) /**< 256kHz nominal. */ -#define STM32_MSIRANGE_512K (3 << 13) /**< 512kHz nominal. */ -#define STM32_MSIRANGE_1M (4 << 13) /**< 1MHz nominal. */ -#define STM32_MSIRANGE_2M (5 << 13) /**< 2MHz nominal. */ -#define STM32_MSIRANGE_4M (6 << 13) /**< 4MHz nominal */ -/** @} */ - -/** - * @name RCC_CSR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 16) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 16) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1 << 16) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2 << 16) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3 << 16) /**< RTC source is HSE divided. */ -/** @} */ - -/** - * @name RCC_CCIPR register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3 << 0) /**< USART1 clock source mask. */ -#define STM32_USART1SEL_APB (0 << 0) /**< USART1 clock is APB. */ -#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ -#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 clock is HSI16. */ -#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 clock is LSE. */ - -#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 clock source mask. */ -#define STM32_USART2SEL_APB (0 << 2) /**< USART2 clock is APB. */ -#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 clock is SYSCLK. */ -#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 clock is HSI16. */ -#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 clock is LSE. */ - -#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 clock source mask. */ -#define STM32_LPUART1SEL_APB (0 << 10) /**< LPUART1 clock is APB. */ -#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 clock is SYSCLK. */ -#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 clock is HSI16. */ -#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 clock is LSE. */ - -#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1 clock source mask. */ -#define STM32_I2C1SEL_APB (0 << 12) /**< I2C1 clock is APB. */ -#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 clock is SYSCLK. */ -#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 clock is HSI16. */ - -#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3 clock source mask. */ -#define STM32_I2C3SEL_APB (0 << 16) /**< I2C3 clock is APB. */ -#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 clock is SYSCLK. */ -#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 clock is HSI16. */ - -#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1 clock source mask. */ -#define STM32_LPTIM1SEL_APB (0 << 18) /**< LPTIM1 clock is APB. */ -#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 clock is LSI. */ -#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 clock is HSI16. */ -#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 clock is LSE. */ - -#define STM32_HSI48SEL_MASK (1 << 26) /**< HSI48SEL clock source mask.*/ -#define STM32_HSI48SEL_USBPLL (0 << 26) /**< USB48 clock is PLL/2. */ -#define STM32_HSI48SEL_HSI48 (1 << 26) /**< USB48 clock is HSI48. */ -/** @} */ - -/** - * @name SYSCFG_CFGR3_ register bits definitions - * @{ - */ -#define STM32_VREFINT_EN (1 << 0) /**< VREFINT enable switch. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_1P8 -#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 HSI16 clock source. - */ -#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSI16 clock divider. - */ -#if !defined(STM32_HSI16_DIVIDER_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_DIVIDER_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 -#endif - -/** - * @brief MSI frequency setting. - */ -#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) -#define STM32_MSIRANGE STM32_MSIRANGE_2M -#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. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed values are 3, 4, 6, 8, 12, 16, 32, 48. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 4 -#endif - -/** - * @brief PLL divider value. - * @note The allowed values are 2, 3, 4. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLDIV_VALUE 2 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief RTC/LCD clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif - -/** - * @brief HSE divider toward RTC setting. - */ -#if !defined(STM32_RTCPRE) || defined(__DOXYGEN__) -#define STM32_RTCPRE STM32_RTCPRE_DIV2 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_APB -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_APB -#endif - -/** - * @brief LPUART1 clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_APB -#endif - -/** - * @brief I2C clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_APB -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_APB -#endif - -/** - * @bief USB/RNG clock source. - */ -#if !defined(STM32_HSI48SEL) || defined(__DOXYGEN__) -#define STM32_HSI48SEL STM32_HSI48SEL_USBPLL -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32L0xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L0xx_MCUCONF not defined" -#endif - -#if defined(STM32L052xx) && !defined(STM32L052_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L052_MCUCONF not defined" - -#elif defined(STM32L053xx) && !defined(STM32L053_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L053_MCUCONF not defined" - -#elif defined(STM32L072xx) && !defined(STM32L072_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L072_MCUCONF not defined" - -#elif defined(STM32L073xx) && !defined(STM32L073_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L073_MCUCONF not defined" - -#endif - -/* - * Board files sanity checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif - -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_1P8) || defined(__DOXYGEN__) -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency at current voltage setting. - */ -#define STM32_SYSCLK_MAX 32000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @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 1000 - -/** - * @brief Maximum PLL input frequency. - */ -#define STM32_PLLIN_MAX 24000000 - -/** - * @brief Maximum PLL input frequency. - */ -#define STM32_PLLIN_MIN 2000000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 96000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 6000000 - -/** - * @brief Maximum PLL output frequency. - */ -#define STM32_PLLOUT_MAX 32000000 - -/** - * @brief Maximum PLL output frequency. - */ -#define STM32_PLLOUT_MIN 2000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 32000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 32000000 - -/** - * @brief Maximum frequency not requiring a wait state for flash accesses. - */ -#define STM32_0WS_THRESHOLD 16000000 - -/** - * @brief HSI availability at current voltage settings. - */ -#define STM32_HSI_AVAILABLE TRUE -/** @} */ - -#elif STM32_VOS == STM32_VOS_1P5 -#define STM32_SYSCLK_MAX 16000000 -#define STM32_HSECLK_MAX 16000000 -#define STM32_HSECLK_MIN 1000000 -#define STM32_LSECLK_MAX 1000000 -#define STM32_LSECLK_MIN 1000 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2000000 -#define STM32_PLLVCO_MAX 48000000 -#define STM32_PLLVCO_MIN 6000000 -#define STM32_PLLOUT_MAX 16000000 -#define STM32_PLLOUT_MIN 2000000 -#define STM32_PCLK1_MAX 16000000 -#define STM32_PCLK2_MAX 16000000 -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_HSI_AVAILABLE TRUE -#elif STM32_VOS == STM32_VOS_1P2 -#define STM32_SYSCLK_MAX 4000000 -#define STM32_HSECLK_MAX 8000000 -#define STM32_HSECLK_MIN 1000000 -#define STM32_LSECLK_MAX 1000000 -#define STM32_LSECLK_MIN 1000 -#define STM32_PLLIN_MAX 8000000 -#define STM32_PLLIN_MIN 2000000 -#define STM32_PLLVCO_MAX 24000000 -#define STM32_PLLVCO_MIN 6000000 -#define STM32_PLLOUT_MAX 4000000 -#define STM32_PLLOUT_MIN 2000000 -#define STM32_PCLK1_MAX 4000000 -#define STM32_PCLK2_MAX 4000000 -#define STM32_0WS_THRESHOLD 4000000 -#define STM32_HSI_AVAILABLE FALSE -#else -#error "invalid STM32_VOS value specified" -#endif - -/* HSI related checks.*/ -#if STM32_HSI16_ENABLED -#if !STM32_HSI_AVAILABLE - #error "impossible to activate HSI under the current voltage settings" -#endif -#else /* !STM32_HSI16_ENABLED */ - -#if STM32_ADC_CLOCK_ENABLED -#error "HSI16 not enabled, required by STM32_ADC_CLOCK_ENABLED" -#endif - -#if (STM32_SW == STM32_SW_HSI16) -#error "HSI16 not enabled, required by STM32_SW" -#endif - -#if ((STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16)) -#error "HSI16 not enabled, required by STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) -#error "HSI16 not enabled, required by STM32_MCOSEL" -#endif - -#if ((STM32_MCOSEL == STM32_MCOSEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16)) -#error "HSI16 not enabled, required by STM32_PLLSRC" -#endif - -#endif /* !STM32_HSI16_ENABLED */ - -/* - * @brief Divided HSI16 clock. - */ -#if STM32_HSI16_DIVIDER_ENABLED || defined(__DOXYGEN__) -#define STM32_HSI16DIVCLK (STM32_HSI16CLK / 4) -#else -#define STM32_HSI16DIVCLK STM32_HSI16CLK -#endif - -/* HSE related checks.*/ -#if STM32_HSE_ENABLED -#if STM32_HSECLK == 0 -#error "impossible to activate HSE, frequency is zero" -#endif -#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif -#else /* !STM32_HSE_ENABLED */ - -#if (STM32_SW == STM32_SW_HSE) -#error "HSE not enabled, required by STM32_SW" -#endif - -#if ((STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if ((STM32_MCOSEL == STM32_MCOSEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_PLLSRC" -#endif - -#if (STM32_RTCSEL == STM32_RTCSEL_HSEDIV) -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* LSI related checks.*/ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_LSI -#error "LSI not enabled, required by STM32_MCOSEL" -#endif - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* LSE related checks.*/ -#if STM32_LSE_ENABLED -#if (STM32_LSECLK == 0) -#error "impossible to activate LSE, frequency is zero" -#endif -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif -#else /* !STM32_LSE_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_LSE -#error "LSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL related checks.*/ -#if (STM32_SW == STM32_SW_PLL) || (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - (STM32_USB_CLOCK_ENABLED && (STM32_HSI48SEL == STM32_HSI48SEL_USBPLL)) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSI48 related checks.*/ -#if (STM32_USB_CLOCK_ENABLED && (STM32_HSI48SEL == STM32_HSI48SEL_HSI48)) || \ - defined(__DOXYGEN__) -/** - * @brief HSI48 activation flag. - */ -#define STM32_ACTIVATE_HSI48 TRUE -#else -#define STM32_ACTIVATE_HSI48 FALSE -#endif - -/** - * @brief PLLMUL field. - */ -#if (STM32_PLLMUL_VALUE == 3) || defined(__DOXYGEN__) -#define STM32_PLLMUL STM32_PLLMUL_MUL3 -#elif STM32_PLLMUL_VALUE == 4 -#define STM32_PLLMUL STM32_PLLMUL_MUL4 -#elif STM32_PLLMUL_VALUE == 6 -#define STM32_PLLMUL STM32_PLLMUL_MUL6 -#elif STM32_PLLMUL_VALUE == 8 -#define STM32_PLLMUL STM32_PLLMUL_MUL8 -#elif STM32_PLLMUL_VALUE == 12 -#define STM32_PLLMUL STM32_PLLMUL_MUL12 -#elif STM32_PLLMUL_VALUE == 16 -#define STM32_PLLMUL STM32_PLLMUL_MUL16 -#elif STM32_PLLMUL_VALUE == 24 -#define STM32_PLLMUL STM32_PLLMUL_MUL24 -#elif STM32_PLLMUL_VALUE == 32 -#define STM32_PLLMUL STM32_PLLMUL_MUL32 -#elif STM32_PLLMUL_VALUE == 48 -#define STM32_PLLMUL STM32_PLLMUL_MUL48 -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLLDIV field. - */ -#if (STM32_PLLDIV_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLDIV STM32_PLLDIV_DIV2 -#elif STM32_PLLDIV_VALUE == 3 -#define STM32_PLLDIV STM32_PLLDIV_DIV3 -#elif STM32_PLLDIV_VALUE == 4 -#define STM32_PLLDIV STM32_PLLDIV_DIV4 -#else -#error "invalid STM32_PLLDIV_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_HSI16 -#define STM32_PLLCLKIN STM32_HSI16DIVCLK -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL 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 - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLDIV_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief MSI frequency. - * @note Values are taken from the STM8Lxx datasheet. - */ -#if STM32_MSIRANGE == STM32_MSIRANGE_64K -#define STM32_MSICLK 65500 -#elif STM32_MSIRANGE == STM32_MSIRANGE_128K -#define STM32_MSICLK 131000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_256K -#define STM32_MSICLK 262000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_512K -#define STM32_MSICLK 524000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_1M -#define STM32_MSICLK 1050000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_2M -#define STM32_MSICLK 2100000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_4M -#define STM32_MSICLK 4200000 -#else -#error "invalid STM32_MSIRANGE value specified" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK 2100000 -#elif (STM32_SW == STM32_SW_MSI) -#define STM32_SYSCLK STM32_MSICLK -#elif (STM32_SW == STM32_SW_HSI16) -#define STM32_SYSCLK STM32_HSI16DIVCLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief MCO selector clock. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK -#define STM32_MCODIVCLK STM32_SYSCLK -#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 -#define STM32_MCODIVCLK STM32_HSI16DIVCLK -#elif STM32_MCOSEL == STM32_MCOSEL_MSI -#define STM32_MCODIVCLK STM32_MSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK -#elif STM32_MCOSEL == STM32_MCOSEL_PLL -#define STM32_MCODIVCLK STM32_PLLCLKOUT -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK -#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 -#define STM32_MCODIVCLK STM32_HSI48CLK -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief HSE divider toward RTC clock. - */ -#if (STM32_RTCPRE == STM32_RTCPRE_DIV2) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 2) -#elif (STM32_RTCPRE == STM32_RTCPRE_DIV4) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 4) -#elif (STM32_RTCPRE == STM32_RTCPRE_DIV8) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 8) -#elif (STM32_RTCPRE == STM32_RTCPRE_DIV16) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 16) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief RTC/LCD clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK STM32_HSEDIVCLK -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_APB) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK2 -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 -#define STM32_USART1CLK STM32_HSI16DIVCLK -#elif STM32_USART1SEL == STM32_USART1SEL_LSE -#define STM32_USART1CLK STM32_LSECLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#if (STM32_USART2SEL == STM32_USART2SEL_APB) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK1 -#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 -#define STM32_USART2CLK STM32_HSI16DIVCLK -#elif STM32_USART2SEL == STM32_USART2SEL_LSE -#define STM32_USART2CLK STM32_LSECLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART4 frequency. - */ -#define STM32_UART4CLK STM32_PCLK1 - -/** - * @brief USART5 frequency. - */ -#define STM32_UART5CLK STM32_PCLK1 - -/** - * @brief LPUART1 frequency. - */ -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_APB) || defined(__DOXYGEN__) -#define STM32_LPUART1CLK STM32_PCLK1 -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK -#define STM32_LPUART1CLK STM32_SYSCLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 -#define STM32_LPUART1CLK STM32_HSI16DIVCLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE -#define STM32_LPUART1CLK STM32_LSECLK -#else -#error "invalid source selected for LPUART1 clock" -#endif - -/** - * @brief I2C1 frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_APB) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK1 -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 -#define STM32_I2C1CLK STM32_HSI16DIVCLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief LPTIM1 frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_APB) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK1 -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI -#define STM32_LPTIM1CLK STM32_LSICLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 -#define STM32_LPTIM1CLK STM32_HSI16DIVCLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE -#define STM32_LPTIM1CLK STM32_LSECLK -#else -#error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief USB clock point. - */ -#if (STM32_HSI48SEL == STM32_HSI48SEL_HSI48) || defined(__DOXYGEN__) -#define STM32_USBCLK STM32_HSI48CLK -#elif STM32_HSI48SEL == STM32_HSI48SEL_USBPLL -#define STM32_USBCLK (STM32_PLLVCO / 2) -#else -#error "invalid STM32_HSI48SEL value specified" -#endif - -/** - * @brief RNG clock point. - */ -#define STM32_RNGCLK STM32_USBCLK - -/** - * @brief Timers LPTIM1, TIM2, TIM6 clock. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers TIM21, TIM22 clock. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0 -#else -#define STM32_FLASHBITS (FLASH_ACR_PRE_READ | \ - FLASH_ACR_PRFTEN | \ - FLASH_ACR_LATENCY) -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L0xx/hal_lld.h + * @brief STM32L0xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32L011xx, STM32L031xx, + * STM32L051xx, STM32L052xx, STM32L053xx, + * STM32L061xx, STM32L062xx, STM32L063xx, + * STM32L071xx, STM32L072xx, STM32L073xx for ultra-low-power MCUs. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +/* + * Registry definitions. + */ +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification macros + * @{ + */ +#if defined(STM32L011xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32L011xx ultra-low-power MCU" + +#elif defined(STM32L031xx) +#define PLATFORM_NAME "STM32L031xx ultra-low-power MCU" + +#elif defined(STM32L051xx) +#define PLATFORM_NAME "STM32L051xx ultra-low-power MCU" + +#elif defined(STM32L052xx) +#define PLATFORM_NAME "STM32L052xx ultra-low-power MCU" + +#elif defined(STM32L053xx) +#define PLATFORM_NAME "STM32L053xx ultra-low-power MCU" + +#elif defined(STM32L061xx) +#define PLATFORM_NAME "STM32L061xx ultra-low-power MCU" + +#elif defined(STM32L062xx) +#define PLATFORM_NAME "STM32L062xx ultra-low-power MCU" + +#elif defined(STM32L063xx) +#define PLATFORM_NAME "STM32L063xx ultra-low-power MCU" + +#elif defined(STM32L071xx) +#define PLATFORM_NAME "STM32L071xx ultra-low-power MCU" + +#elif defined(STM32L072xx) +#define PLATFORM_NAME "STM32L073xx ultra-low-power MCU" + +#elif defined(STM32L073xx) +#define PLATFORM_NAME "STM32L073xx ultra-low-power MCU" + +#else +#error "STM32L0xx device not specified" +#endif +/** @} */ + +/** + * @name Sub-family identifier + */ +#if !defined(STM32L0XX) || defined(__DOXYGEN__) +#define STM32L0XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ +#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ +#define STM32_LSICLK 37000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7 << 5) /**< PLS field mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_EXT (7 << 5) /**< PVD level 7. */ + +#define STM32_VOS_MASK (3 << 11) /**< VOS field mask. */ +#define STM32_VOS_1P8 (1 << 11) /**< VOS level 1.8 volts. */ +#define STM32_VOS_1P5 (2 << 11) /**< VOS level 1.5 volts. */ +#define STM32_VOS_1P2 (3 << 11) /**< VOS level 1.2 volts. */ +/** @} */ + +/** + * @name RCC_CR register bits definitions + * @{ + */ +#define STM32_RTCPRE_MASK (3 << 20) /**< RTCPRE mask. */ +#define STM32_RTCPRE_DIV2 (0 << 20) /**< HSE divided by 2. */ +#define STM32_RTCPRE_DIV4 (1 << 20) /**< HSE divided by 4. */ +#define STM32_RTCPRE_DIV8 (2 << 20) /**< HSE divided by 2. */ +#define STM32_RTCPRE_DIV16 (3 << 20) /**< HSE divided by 16. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ +#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ +#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI16 */ +#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 8) /**< PPRE2 field mask. */ +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_STOPWUCK_MASK (1 << 15) /**< PLLDIV field mask. */ +#define STM32_STOPWUCK_MSI (0 << 15) /**< MSI is wakeup clock. */ +#define STM32_STOPWUCK_HSI16 (1 << 15) /**< HSI16 is wakeup clock. */ + +#define STM32_PLLSRC_MASK (1 << 16) /**< PLLSRC field mask. */ +#define STM32_PLLSRC_HSI16 (0 << 16) /**< PLL clock source is HSI16. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ + +#define STM32_PLLMUL_MASK (15 << 18) /**< PLLMUL field mask. */ +#define STM32_PLLMUL_MUL3 (0 << 18) /**< PLL multiplier is 3. */ +#define STM32_PLLMUL_MUL4 (1 << 18) /**< PLL multiplier is 4. */ +#define STM32_PLLMUL_MUL6 (2 << 18) /**< PLL multiplier is 6. */ +#define STM32_PLLMUL_MUL8 (3 << 18) /**< PLL multiplier is 8. */ +#define STM32_PLLMUL_MUL12 (4 << 18) /**< PLL multiplier is 12. */ +#define STM32_PLLMUL_MUL16 (5 << 18) /**< PLL multiplier is 16. */ +#define STM32_PLLMUL_MUL24 (6 << 18) /**< PLL multiplier is 24. */ +#define STM32_PLLMUL_MUL32 (7 << 18) /**< PLL multiplier is 32. */ +#define STM32_PLLMUL_MUL48 (8 << 18) /**< PLL multiplier is 48. */ + +#define STM32_PLLDIV_MASK (3 << 22) /**< PLLDIV field mask. */ +#define STM32_PLLDIV_DIV2 (1 << 22) /**< PLL divided by 2. */ +#define STM32_PLLDIV_DIV3 (2 << 22) /**< PLL divided by 3. */ +#define STM32_PLLDIV_DIV4 (3 << 22) /**< PLL divided by 4. */ + +#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI16 (2 << 24) /**< HSI16 clock on MCO pin. */ +#define STM32_MCOSEL_MSI (3 << 24) /**< MSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ + +#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ +#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO is divided by 1. */ +#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO is divided by 1. */ +#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO is divided by 1. */ +#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO is divided by 1. */ +#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO is divided by 1. */ +/** @} */ + +/** + * @name RCC_ICSCR register bits definitions + * @{ + */ +#define STM32_MSIRANGE_MASK (7 << 13) /**< MSIRANGE field mask. */ +#define STM32_MSIRANGE_64K (0 << 13) /**< 64kHz nominal. */ +#define STM32_MSIRANGE_128K (1 << 13) /**< 128kHz nominal. */ +#define STM32_MSIRANGE_256K (2 << 13) /**< 256kHz nominal. */ +#define STM32_MSIRANGE_512K (3 << 13) /**< 512kHz nominal. */ +#define STM32_MSIRANGE_1M (4 << 13) /**< 1MHz nominal. */ +#define STM32_MSIRANGE_2M (5 << 13) /**< 2MHz nominal. */ +#define STM32_MSIRANGE_4M (6 << 13) /**< 4MHz nominal */ +/** @} */ + +/** + * @name RCC_CSR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 16) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 16) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1 << 16) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2 << 16) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3 << 16) /**< RTC source is HSE divided. */ +/** @} */ + +/** + * @name RCC_CCIPR register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3 << 0) /**< USART1 clock source mask. */ +#define STM32_USART1SEL_APB (0 << 0) /**< USART1 clock is APB. */ +#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ +#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 clock is HSI16. */ +#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 clock is LSE. */ + +#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 clock source mask. */ +#define STM32_USART2SEL_APB (0 << 2) /**< USART2 clock is APB. */ +#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 clock is SYSCLK. */ +#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 clock is HSI16. */ +#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 clock is LSE. */ + +#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 clock source mask. */ +#define STM32_LPUART1SEL_APB (0 << 10) /**< LPUART1 clock is APB. */ +#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 clock is SYSCLK. */ +#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 clock is HSI16. */ +#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 clock is LSE. */ + +#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1 clock source mask. */ +#define STM32_I2C1SEL_APB (0 << 12) /**< I2C1 clock is APB. */ +#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 clock is SYSCLK. */ +#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 clock is HSI16. */ + +#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3 clock source mask. */ +#define STM32_I2C3SEL_APB (0 << 16) /**< I2C3 clock is APB. */ +#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 clock is SYSCLK. */ +#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 clock is HSI16. */ + +#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1 clock source mask. */ +#define STM32_LPTIM1SEL_APB (0 << 18) /**< LPTIM1 clock is APB. */ +#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 clock is LSI. */ +#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 clock is HSI16. */ +#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 clock is LSE. */ + +#define STM32_HSI48SEL_MASK (1 << 26) /**< HSI48SEL clock source mask.*/ +#define STM32_HSI48SEL_USBPLL (0 << 26) /**< USB48 clock is PLL/2. */ +#define STM32_HSI48SEL_HSI48 (1 << 26) /**< USB48 clock is HSI48. */ +/** @} */ + +/** + * @name SYSCFG_CFGR3_ register bits definitions + * @{ + */ +#define STM32_VREFINT_EN (1 << 0) /**< VREFINT enable switch. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_1P8 +#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 HSI16 clock source. + */ +#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSI16 clock divider. + */ +#if !defined(STM32_HSI16_DIVIDER_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_DIVIDER_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 +#endif + +/** + * @brief MSI frequency setting. + */ +#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) +#define STM32_MSIRANGE STM32_MSIRANGE_2M +#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. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed values are 3, 4, 6, 8, 12, 16, 32, 48. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 4 +#endif + +/** + * @brief PLL divider value. + * @note The allowed values are 2, 3, 4. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLDIV_VALUE 2 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief RTC/LCD clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif + +/** + * @brief HSE divider toward RTC setting. + */ +#if !defined(STM32_RTCPRE) || defined(__DOXYGEN__) +#define STM32_RTCPRE STM32_RTCPRE_DIV2 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_APB +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_APB +#endif + +/** + * @brief LPUART1 clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_APB +#endif + +/** + * @brief I2C clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_APB +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_APB +#endif + +/** + * @bief USB/RNG clock source. + */ +#if !defined(STM32_HSI48SEL) || defined(__DOXYGEN__) +#define STM32_HSI48SEL STM32_HSI48SEL_USBPLL +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32L0xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L0xx_MCUCONF not defined" +#endif + +#if defined(STM32L052xx) && !defined(STM32L052_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L052_MCUCONF not defined" + +#elif defined(STM32L053xx) && !defined(STM32L053_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L053_MCUCONF not defined" + +#elif defined(STM32L072xx) && !defined(STM32L072_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L072_MCUCONF not defined" + +#elif defined(STM32L073xx) && !defined(STM32L073_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L073_MCUCONF not defined" + +#endif + +/* + * Board files sanity checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif + +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_1P8) || defined(__DOXYGEN__) +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum SYSCLK clock frequency at current voltage setting. + */ +#define STM32_SYSCLK_MAX 32000000 + +/** + * @brief Maximum HSE clock frequency at current voltage setting. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @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 1000 + +/** + * @brief Maximum PLL input frequency. + */ +#define STM32_PLLIN_MAX 24000000 + +/** + * @brief Maximum PLL input frequency. + */ +#define STM32_PLLIN_MIN 2000000 + +/** + * @brief Maximum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MAX 96000000 + +/** + * @brief Minimum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MIN 6000000 + +/** + * @brief Maximum PLL output frequency. + */ +#define STM32_PLLOUT_MAX 32000000 + +/** + * @brief Maximum PLL output frequency. + */ +#define STM32_PLLOUT_MIN 2000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 32000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 32000000 + +/** + * @brief Maximum frequency not requiring a wait state for flash accesses. + */ +#define STM32_0WS_THRESHOLD 16000000 + +/** + * @brief HSI availability at current voltage settings. + */ +#define STM32_HSI_AVAILABLE TRUE +/** @} */ + +#elif STM32_VOS == STM32_VOS_1P5 +#define STM32_SYSCLK_MAX 16000000 +#define STM32_HSECLK_MAX 16000000 +#define STM32_HSECLK_MIN 1000000 +#define STM32_LSECLK_MAX 1000000 +#define STM32_LSECLK_MIN 1000 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MIN 2000000 +#define STM32_PLLVCO_MAX 48000000 +#define STM32_PLLVCO_MIN 6000000 +#define STM32_PLLOUT_MAX 16000000 +#define STM32_PLLOUT_MIN 2000000 +#define STM32_PCLK1_MAX 16000000 +#define STM32_PCLK2_MAX 16000000 +#define STM32_0WS_THRESHOLD 8000000 +#define STM32_HSI_AVAILABLE TRUE +#elif STM32_VOS == STM32_VOS_1P2 +#define STM32_SYSCLK_MAX 4000000 +#define STM32_HSECLK_MAX 8000000 +#define STM32_HSECLK_MIN 1000000 +#define STM32_LSECLK_MAX 1000000 +#define STM32_LSECLK_MIN 1000 +#define STM32_PLLIN_MAX 8000000 +#define STM32_PLLIN_MIN 2000000 +#define STM32_PLLVCO_MAX 24000000 +#define STM32_PLLVCO_MIN 6000000 +#define STM32_PLLOUT_MAX 4000000 +#define STM32_PLLOUT_MIN 2000000 +#define STM32_PCLK1_MAX 4000000 +#define STM32_PCLK2_MAX 4000000 +#define STM32_0WS_THRESHOLD 4000000 +#define STM32_HSI_AVAILABLE FALSE +#else +#error "invalid STM32_VOS value specified" +#endif + +/* HSI related checks.*/ +#if STM32_HSI16_ENABLED +#if !STM32_HSI_AVAILABLE + #error "impossible to activate HSI under the current voltage settings" +#endif +#else /* !STM32_HSI16_ENABLED */ + +#if STM32_ADC_CLOCK_ENABLED +#error "HSI16 not enabled, required by STM32_ADC_CLOCK_ENABLED" +#endif + +#if (STM32_SW == STM32_SW_HSI16) +#error "HSI16 not enabled, required by STM32_SW" +#endif + +#if ((STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16)) +#error "HSI16 not enabled, required by STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) +#error "HSI16 not enabled, required by STM32_MCOSEL" +#endif + +#if ((STM32_MCOSEL == STM32_MCOSEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16)) +#error "HSI16 not enabled, required by STM32_PLLSRC" +#endif + +#endif /* !STM32_HSI16_ENABLED */ + +/* + * @brief Divided HSI16 clock. + */ +#if STM32_HSI16_DIVIDER_ENABLED || defined(__DOXYGEN__) +#define STM32_HSI16DIVCLK (STM32_HSI16CLK / 4) +#else +#define STM32_HSI16DIVCLK STM32_HSI16CLK +#endif + +/* HSE related checks.*/ +#if STM32_HSE_ENABLED +#if STM32_HSECLK == 0 +#error "impossible to activate HSE, frequency is zero" +#endif +#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif +#else /* !STM32_HSE_ENABLED */ + +#if (STM32_SW == STM32_SW_HSE) +#error "HSE not enabled, required by STM32_SW" +#endif + +#if ((STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if ((STM32_MCOSEL == STM32_MCOSEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_PLLSRC" +#endif + +#if (STM32_RTCSEL == STM32_RTCSEL_HSEDIV) +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* LSI related checks.*/ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_LSI +#error "LSI not enabled, required by STM32_MCOSEL" +#endif + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* LSE related checks.*/ +#if STM32_LSE_ENABLED +#if (STM32_LSECLK == 0) +#error "impossible to activate LSE, frequency is zero" +#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 (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_LSE +#error "LSE not enabled, required by STM32_MCOSEL" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL related checks.*/ +#if (STM32_SW == STM32_SW_PLL) || (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + (STM32_USB_CLOCK_ENABLED && (STM32_HSI48SEL == STM32_HSI48SEL_USBPLL)) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSI48 related checks.*/ +#if (STM32_USB_CLOCK_ENABLED && (STM32_HSI48SEL == STM32_HSI48SEL_HSI48)) || \ + defined(__DOXYGEN__) +/** + * @brief HSI48 activation flag. + */ +#define STM32_ACTIVATE_HSI48 TRUE +#else +#define STM32_ACTIVATE_HSI48 FALSE +#endif + +/** + * @brief PLLMUL field. + */ +#if (STM32_PLLMUL_VALUE == 3) || defined(__DOXYGEN__) +#define STM32_PLLMUL STM32_PLLMUL_MUL3 +#elif STM32_PLLMUL_VALUE == 4 +#define STM32_PLLMUL STM32_PLLMUL_MUL4 +#elif STM32_PLLMUL_VALUE == 6 +#define STM32_PLLMUL STM32_PLLMUL_MUL6 +#elif STM32_PLLMUL_VALUE == 8 +#define STM32_PLLMUL STM32_PLLMUL_MUL8 +#elif STM32_PLLMUL_VALUE == 12 +#define STM32_PLLMUL STM32_PLLMUL_MUL12 +#elif STM32_PLLMUL_VALUE == 16 +#define STM32_PLLMUL STM32_PLLMUL_MUL16 +#elif STM32_PLLMUL_VALUE == 24 +#define STM32_PLLMUL STM32_PLLMUL_MUL24 +#elif STM32_PLLMUL_VALUE == 32 +#define STM32_PLLMUL STM32_PLLMUL_MUL32 +#elif STM32_PLLMUL_VALUE == 48 +#define STM32_PLLMUL STM32_PLLMUL_MUL48 +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLLDIV field. + */ +#if (STM32_PLLDIV_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLDIV STM32_PLLDIV_DIV2 +#elif STM32_PLLDIV_VALUE == 3 +#define STM32_PLLDIV STM32_PLLDIV_DIV3 +#elif STM32_PLLDIV_VALUE == 4 +#define STM32_PLLDIV STM32_PLLDIV_DIV4 +#else +#error "invalid STM32_PLLDIV_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_HSI16 +#define STM32_PLLCLKIN STM32_HSI16DIVCLK +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL 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 + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLDIV_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief MSI frequency. + * @note Values are taken from the STM8Lxx datasheet. + */ +#if STM32_MSIRANGE == STM32_MSIRANGE_64K +#define STM32_MSICLK 65500 +#elif STM32_MSIRANGE == STM32_MSIRANGE_128K +#define STM32_MSICLK 131000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_256K +#define STM32_MSICLK 262000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_512K +#define STM32_MSICLK 524000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_1M +#define STM32_MSICLK 1050000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_2M +#define STM32_MSICLK 2100000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_4M +#define STM32_MSICLK 4200000 +#else +#error "invalid STM32_MSIRANGE value specified" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK 2100000 +#elif (STM32_SW == STM32_SW_MSI) +#define STM32_SYSCLK STM32_MSICLK +#elif (STM32_SW == STM32_SW_HSI16) +#define STM32_SYSCLK STM32_HSI16DIVCLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief MCO selector clock. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK +#define STM32_MCODIVCLK STM32_SYSCLK +#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 +#define STM32_MCODIVCLK STM32_HSI16DIVCLK +#elif STM32_MCOSEL == STM32_MCOSEL_MSI +#define STM32_MCODIVCLK STM32_MSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK +#elif STM32_MCOSEL == STM32_MCOSEL_PLL +#define STM32_MCODIVCLK STM32_PLLCLKOUT +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK +#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 +#define STM32_MCODIVCLK STM32_HSI48CLK +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief HSE divider toward RTC clock. + */ +#if (STM32_RTCPRE == STM32_RTCPRE_DIV2) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 2) +#elif (STM32_RTCPRE == STM32_RTCPRE_DIV4) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 4) +#elif (STM32_RTCPRE == STM32_RTCPRE_DIV8) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 8) +#elif (STM32_RTCPRE == STM32_RTCPRE_DIV16) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 16) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief RTC/LCD clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK STM32_HSEDIVCLK +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_APB) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK2 +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 +#define STM32_USART1CLK STM32_HSI16DIVCLK +#elif STM32_USART1SEL == STM32_USART1SEL_LSE +#define STM32_USART1CLK STM32_LSECLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#if (STM32_USART2SEL == STM32_USART2SEL_APB) || defined(__DOXYGEN__) +#define STM32_USART2CLK STM32_PCLK1 +#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 +#define STM32_USART2CLK STM32_HSI16DIVCLK +#elif STM32_USART2SEL == STM32_USART2SEL_LSE +#define STM32_USART2CLK STM32_LSECLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART4 frequency. + */ +#define STM32_UART4CLK STM32_PCLK1 + +/** + * @brief USART5 frequency. + */ +#define STM32_UART5CLK STM32_PCLK1 + +/** + * @brief LPUART1 frequency. + */ +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_APB) || defined(__DOXYGEN__) +#define STM32_LPUART1CLK STM32_PCLK1 +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK +#define STM32_LPUART1CLK STM32_SYSCLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 +#define STM32_LPUART1CLK STM32_HSI16DIVCLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE +#define STM32_LPUART1CLK STM32_LSECLK +#else +#error "invalid source selected for LPUART1 clock" +#endif + +/** + * @brief I2C1 frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_APB) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_PCLK1 +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 +#define STM32_I2C1CLK STM32_HSI16DIVCLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief LPTIM1 frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_APB) || defined(__DOXYGEN__) +#define STM32_LPTIM1CLK STM32_PCLK1 +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI +#define STM32_LPTIM1CLK STM32_LSICLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 +#define STM32_LPTIM1CLK STM32_HSI16DIVCLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE +#define STM32_LPTIM1CLK STM32_LSECLK +#else +#error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief USB clock point. + */ +#if (STM32_HSI48SEL == STM32_HSI48SEL_HSI48) || defined(__DOXYGEN__) +#define STM32_USBCLK STM32_HSI48CLK +#elif STM32_HSI48SEL == STM32_HSI48SEL_USBPLL +#define STM32_USBCLK (STM32_PLLVCO / 2) +#else +#error "invalid STM32_HSI48SEL value specified" +#endif + +/** + * @brief RNG clock point. + */ +#define STM32_RNGCLK STM32_USBCLK + +/** + * @brief Timers LPTIM1, TIM2, TIM6 clock. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers TIM21, TIM22 clock. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0 +#else +#define STM32_FLASHBITS (FLASH_ACR_PRE_READ | \ + FLASH_ACR_PRFTEN | \ + FLASH_ACR_LATENCY) +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L0xx/platform.mk b/os/hal/ports/STM32/STM32L0xx/platform.mk index 208d410149..2e48dad746 100644 --- a/os/hal/ports/STM32/STM32L0xx/platform.mk +++ b/os/hal/ports/STM32/STM32L0xx/platform.mk @@ -1,45 +1,45 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L0xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L0xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L0xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L0xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L0xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L0xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32L0xx/stm32_isr.c b/os/hal/ports/STM32/STM32L0xx/stm32_isr.c index e8417a192d..d7dfc96699 100644 --- a/os/hal/ports/STM32/STM32L0xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32L0xx/stm32_isr.c @@ -1,125 +1,125 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L0xx/stm32_isr.c - * @brief STM32L0xx ISR handler code. - * - * @addtogroup SRM32L0xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_dma1_ch23.inc" -#include "stm32_dma1_ch4567.inc" - -#include "stm32_exti0_1.inc" -#include "stm32_exti2_3.inc" -#include "stm32_exti4_15.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart4_5.inc" -#include "stm32_lpuart1.inc" - -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim21.inc" -#include "stm32_tim22.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_1_irq_init(); - exti2_3_irq_init(); - exti4_15_irq_init(); - - tim2_irq_init(); - tim3_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim21_irq_init(); - tim22_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart4_usart5_irq_init(); - lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_1_irq_deinit(); - exti2_3_irq_deinit(); - exti4_15_irq_deinit(); - - tim2_irq_deinit(); - tim3_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim21_irq_deinit(); - tim22_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart4_usart5_irq_deinit(); - lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L0xx/stm32_isr.c + * @brief STM32L0xx ISR handler code. + * + * @addtogroup SRM32L0xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_dma1_ch23.inc" +#include "stm32_dma1_ch4567.inc" + +#include "stm32_exti0_1.inc" +#include "stm32_exti2_3.inc" +#include "stm32_exti4_15.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart4_5.inc" +#include "stm32_lpuart1.inc" + +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim21.inc" +#include "stm32_tim22.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_1_irq_init(); + exti2_3_irq_init(); + exti4_15_irq_init(); + + tim2_irq_init(); + tim3_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim21_irq_init(); + tim22_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart4_usart5_irq_init(); + lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_1_irq_deinit(); + exti2_3_irq_deinit(); + exti4_15_irq_deinit(); + + tim2_irq_deinit(); + tim3_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim21_irq_deinit(); + tim22_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart4_usart5_irq_deinit(); + lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L0xx/stm32_isr.h b/os/hal/ports/STM32/STM32L0xx/stm32_isr.h index fc31e0ab78..3a332634fb 100644 --- a/os/hal/ports/STM32/STM32L0xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32L0xx/stm32_isr.h @@ -1,182 +1,182 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L0xx/stm32_isr.h - * @brief STM32L0xx ISR handler header. - * - * @addtogroup STM32L0xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM21_SUPPRESS_ISR -#define STM32_TIM22_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC unit. - */ -#define STM32_ADC1_HANDLER Vector70 -#define STM32_ADC1_NUMBER 12 - -/* - * DMA unit. - */ -#define STM32_DMA1_CH1_HANDLER Vector64 -#define STM32_DMA1_CH23_HANDLER Vector68 -#define STM32_DMA1_CH4567_HANDLER Vector6C -#define STM32_DMA1_CH1_NUMBER 9 -#define STM32_DMA1_CH23_NUMBER 10 -#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER -#define STM32_DMA1_CH4567_NUMBER 11 -#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER -#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER - -#define STM32_DMA1_CH2_CMASK 0x00000006U -#define STM32_DMA1_CH3_CMASK 0x00000006U -#define STM32_DMA1_CH4_CMASK 0x00000078U -#define STM32_DMA1_CH5_CMASK 0x00000078U -#define STM32_DMA1_CH6_CMASK 0x00000078U -#define STM32_DMA1_CH7_CMASK 0x00000078U - -/* - * EXTI unit. - */ -#define STM32_EXTI0_1_HANDLER Vector54 -#define STM32_EXTI2_3_HANDLER Vector58 -#define STM32_EXTI4_15_HANDLER Vector5C -#define STM32_EXTI16_HANDLER Vector44 -#define STM32_EXTI171920_HANDLER Vector48 -#define STM32_EXTI2122_HANDLER Vector70 - -#define STM32_EXTI0_1_NUMBER 5 -#define STM32_EXTI2_3_NUMBER 6 -#define STM32_EXTI4_15_NUMBER 7 -#define STM32_EXTI16_NUMBER 1 -#define STM32_EXTI171920_NUMBER 2 -#define STM32_EXTI2122_NUMBER 12 - -/* - * I2C units. - */ -#define STM32_I2C1_GLOBAL_HANDLER Vector9C -#define STM32_I2C2_GLOBAL_HANDLER VectorA0 -#define STM32_I2C3_GLOBAL_HANDLER Vector94 - -#define STM32_I2C1_GLOBAL_NUMBER 23 -#define STM32_I2C2_GLOBAL_NUMBER 24 -#define STM32_I2C3_GLOBAL_NUMBER 21 - -/* - * TIM units. - */ -#define STM32_TIM2_HANDLER Vector7C -#define STM32_TIM3_HANDLER Vector80 -#define STM32_TIM6_HANDLER Vector84 -#define STM32_TIM7_HANDLER Vector88 -#define STM32_TIM21_HANDLER Vector90 -#define STM32_TIM22_HANDLER Vector98 - -#define STM32_TIM2_NUMBER 15 -#define STM32_TIM3_NUMBER 16 -#define STM32_TIM6_NUMBER 17 -#define STM32_TIM7_NUMBER 18 -#define STM32_TIM21_NUMBER 20 -#define STM32_TIM22_NUMBER 22 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorAC -#define STM32_USART2_HANDLER VectorB0 -#define STM32_USART4_5_HANDLER Vector78 -#define STM32_LPUART1_HANDLER VectorB4 - -#define STM32_USART1_NUMBER 27 -#define STM32_USART2_NUMBER 28 -#define STM32_USART4_5_NUMBER 14 -#define STM32_LPUART1_NUMBER 29 - -/* - * USB units. - */ -#define STM32_USB1_LP_HANDLER VectorBC -#define STM32_USB1_HP_HANDLER VectorBC - -#define STM32_USB1_LP_NUMBER 31 -#define STM32_USB1_HP_NUMBER 31 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L0xx/stm32_isr.h + * @brief STM32L0xx ISR handler header. + * + * @addtogroup STM32L0xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM21_SUPPRESS_ISR +#define STM32_TIM22_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC unit. + */ +#define STM32_ADC1_HANDLER Vector70 +#define STM32_ADC1_NUMBER 12 + +/* + * DMA unit. + */ +#define STM32_DMA1_CH1_HANDLER Vector64 +#define STM32_DMA1_CH23_HANDLER Vector68 +#define STM32_DMA1_CH4567_HANDLER Vector6C +#define STM32_DMA1_CH1_NUMBER 9 +#define STM32_DMA1_CH23_NUMBER 10 +#define STM32_DMA1_CH2_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH3_NUMBER STM32_DMA1_CH23_NUMBER +#define STM32_DMA1_CH4567_NUMBER 11 +#define STM32_DMA1_CH4_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH5_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH6_NUMBER STM32_DMA1_CH4567_NUMBER +#define STM32_DMA1_CH7_NUMBER STM32_DMA1_CH4567_NUMBER + +#define STM32_DMA1_CH2_CMASK 0x00000006U +#define STM32_DMA1_CH3_CMASK 0x00000006U +#define STM32_DMA1_CH4_CMASK 0x00000078U +#define STM32_DMA1_CH5_CMASK 0x00000078U +#define STM32_DMA1_CH6_CMASK 0x00000078U +#define STM32_DMA1_CH7_CMASK 0x00000078U + +/* + * EXTI unit. + */ +#define STM32_EXTI0_1_HANDLER Vector54 +#define STM32_EXTI2_3_HANDLER Vector58 +#define STM32_EXTI4_15_HANDLER Vector5C +#define STM32_EXTI16_HANDLER Vector44 +#define STM32_EXTI171920_HANDLER Vector48 +#define STM32_EXTI2122_HANDLER Vector70 + +#define STM32_EXTI0_1_NUMBER 5 +#define STM32_EXTI2_3_NUMBER 6 +#define STM32_EXTI4_15_NUMBER 7 +#define STM32_EXTI16_NUMBER 1 +#define STM32_EXTI171920_NUMBER 2 +#define STM32_EXTI2122_NUMBER 12 + +/* + * I2C units. + */ +#define STM32_I2C1_GLOBAL_HANDLER Vector9C +#define STM32_I2C2_GLOBAL_HANDLER VectorA0 +#define STM32_I2C3_GLOBAL_HANDLER Vector94 + +#define STM32_I2C1_GLOBAL_NUMBER 23 +#define STM32_I2C2_GLOBAL_NUMBER 24 +#define STM32_I2C3_GLOBAL_NUMBER 21 + +/* + * TIM units. + */ +#define STM32_TIM2_HANDLER Vector7C +#define STM32_TIM3_HANDLER Vector80 +#define STM32_TIM6_HANDLER Vector84 +#define STM32_TIM7_HANDLER Vector88 +#define STM32_TIM21_HANDLER Vector90 +#define STM32_TIM22_HANDLER Vector98 + +#define STM32_TIM2_NUMBER 15 +#define STM32_TIM3_NUMBER 16 +#define STM32_TIM6_NUMBER 17 +#define STM32_TIM7_NUMBER 18 +#define STM32_TIM21_NUMBER 20 +#define STM32_TIM22_NUMBER 22 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorAC +#define STM32_USART2_HANDLER VectorB0 +#define STM32_USART4_5_HANDLER Vector78 +#define STM32_LPUART1_HANDLER VectorB4 + +#define STM32_USART1_NUMBER 27 +#define STM32_USART2_NUMBER 28 +#define STM32_USART4_5_NUMBER 14 +#define STM32_LPUART1_NUMBER 29 + +/* + * USB units. + */ +#define STM32_USB1_LP_HANDLER VectorBC +#define STM32_USB1_HP_HANDLER VectorBC + +#define STM32_USB1_LP_NUMBER 31 +#define STM32_USB1_HP_NUMBER 31 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L0xx/stm32_rcc.h b/os/hal/ports/STM32/STM32L0xx/stm32_rcc.h index 696ae64cf2..644d40a61c 100644 --- a/os/hal/ports/STM32/STM32L0xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32L0xx/stm32_rcc.h @@ -1,819 +1,819 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L0xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32l0xx.h. - * - * @addtogroup STM32L1xx_RCC - * @{ - */ - -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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->APB1SMENR |= (mask); \ - else \ - RCC->APB1SMENR &= ~(mask); \ - (void)RCC->APB1SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - RCC->APB1SMENR &= ~(mask); \ - (void)RCC->APB1SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @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->APB2SMENR |= (mask); \ - else \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - if (lp) \ - RCC->AHBSMENR |= (mask); \ - else \ - RCC->AHBSMENR &= ~(mask); \ - (void)RCC->AHBSMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - RCC->AHBSMENR &= ~(mask); \ - (void)RCC->AHBSMENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the IOP bus. - * - * @param[in] mask IOP peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableIOP(mask, lp) { \ - RCC->IOPENR |= (mask); \ - if (lp) \ - RCC->IOPSMENR |= (mask); \ - else \ - RCC->IOPSMENR &= ~(mask); \ - (void)RCC->IOPSMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the IOP bus. - * - * @param[in] mask IOP peripherals mask - * - * @api - */ -#define rccDisableIOP(mask) { \ - RCC->IOPENR &= ~(mask); \ - RCC->IOPSMENR &= ~(mask); \ - (void)RCC->IOPSMENR; \ -} - -/** - * @brief Resets one or more peripheral on the IOP bus. - * - * @param[in] mask IOP peripherals mask - * - * @api - */ -#define rccResetIOP(mask) { \ - RCC->IOPRSTR |= (mask); \ - RCC->IOPRSTR &= ~(mask); \ - (void)RCC->IOPRSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1(RCC_APB1ENR_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB(RCC_AHBENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB(RCC_AHBENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB(RCC_AHBRSTR_RNGRST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM21 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM21(lp) rccEnableAPB2(RCC_APB2ENR_TIM21EN, lp) - -/** - * @brief Disables the TIM21 peripheral clock. - * - * @api - */ -#define rccDisableTIM21() rccDisableAPB2(RCC_APB2ENR_TIM21EN) - -/** - * @brief Resets the TIM21 peripheral. - * - * @api - */ -#define rccResetTIM21() rccResetAPB2(RCC_APB2RSTR_TIM21RST) - -/** - * @brief Enables the TIM22 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM22(lp) rccEnableAPB2(RCC_APB2ENR_TIM22EN, lp) - -/** - * @brief Disables the TIM22 peripheral clock. - * - * @api - */ -#define rccDisableTIM22() rccDisableAPB2(RCC_APB2ENR_TIM22EN) - -/** - * @brief Resets the TIM22 peripheral. - * - * @api - */ -#define rccResetTIM22() rccResetAPB2(RCC_APB2RSTR_TIM22RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_USART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_USART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1ENR_USART4EN) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_USART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_USART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1ENR_USART5EN) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPB1(RCC_APB1ENR_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPB1(RCC_APB1ENR_LPUART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPB1(RCC_APB1RSTR_LPUART1RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L0xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32l0xx.h. + * + * @addtogroup STM32L1xx_RCC + * @{ + */ + +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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->APB1SMENR |= (mask); \ + else \ + RCC->APB1SMENR &= ~(mask); \ + (void)RCC->APB1SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + RCC->APB1SMENR &= ~(mask); \ + (void)RCC->APB1SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @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->APB2SMENR |= (mask); \ + else \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + if (lp) \ + RCC->AHBSMENR |= (mask); \ + else \ + RCC->AHBSMENR &= ~(mask); \ + (void)RCC->AHBSMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + RCC->AHBSMENR &= ~(mask); \ + (void)RCC->AHBSMENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the IOP bus. + * + * @param[in] mask IOP peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableIOP(mask, lp) { \ + RCC->IOPENR |= (mask); \ + if (lp) \ + RCC->IOPSMENR |= (mask); \ + else \ + RCC->IOPSMENR &= ~(mask); \ + (void)RCC->IOPSMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the IOP bus. + * + * @param[in] mask IOP peripherals mask + * + * @api + */ +#define rccDisableIOP(mask) { \ + RCC->IOPENR &= ~(mask); \ + RCC->IOPSMENR &= ~(mask); \ + (void)RCC->IOPSMENR; \ +} + +/** + * @brief Resets one or more peripheral on the IOP bus. + * + * @param[in] mask IOP peripherals mask + * + * @api + */ +#define rccResetIOP(mask) { \ + RCC->IOPRSTR |= (mask); \ + RCC->IOPRSTR &= ~(mask); \ + (void)RCC->IOPRSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1(RCC_APB1ENR_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB(RCC_AHBENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB(RCC_AHBENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB(RCC_AHBRSTR_RNGRST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM21 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM21(lp) rccEnableAPB2(RCC_APB2ENR_TIM21EN, lp) + +/** + * @brief Disables the TIM21 peripheral clock. + * + * @api + */ +#define rccDisableTIM21() rccDisableAPB2(RCC_APB2ENR_TIM21EN) + +/** + * @brief Resets the TIM21 peripheral. + * + * @api + */ +#define rccResetTIM21() rccResetAPB2(RCC_APB2RSTR_TIM21RST) + +/** + * @brief Enables the TIM22 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM22(lp) rccEnableAPB2(RCC_APB2ENR_TIM22EN, lp) + +/** + * @brief Disables the TIM22 peripheral clock. + * + * @api + */ +#define rccDisableTIM22() rccDisableAPB2(RCC_APB2ENR_TIM22EN) + +/** + * @brief Resets the TIM22 peripheral. + * + * @api + */ +#define rccResetTIM22() rccResetAPB2(RCC_APB2RSTR_TIM22RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_USART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_USART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1ENR_USART4EN) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_USART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_USART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1ENR_USART5EN) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPB1(RCC_APB1ENR_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPB1(RCC_APB1ENR_LPUART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPB1(RCC_APB1RSTR_LPUART1RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L0xx/stm32_registry.h b/os/hal/ports/STM32/STM32L0xx/stm32_registry.h index 7784ffc4c4..067b07d0fa 100644 --- a/os/hal/ports/STM32/STM32L0xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L0xx/stm32_registry.h @@ -1,1220 +1,1220 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L0xx/stm32_registry.h - * @brief STM32L0xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32L0xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 20 -#define STM32_RTC_COMMON_HANDLER Vector48 -#define STM32_RTC_COMMON_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() \ - nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_PRIORITY) - -/*===========================================================================*/ -/* STM32L011xx. */ -/*===========================================================================*/ -#if defined(STM32L011xx) || defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER TRUE -#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 5 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0xFF840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x06000600 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00600060 - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000010 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00000100 - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM21 TRUE -#define STM32_TIM21_IS_32BITS FALSE -#define STM32_TIM21_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00440000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x04004000 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART1 FALSE -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32L031xx. */ -/*===========================================================================*/ -#elif defined(STM32L031xx) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER TRUE -#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0xFF840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x06000600 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00600060 - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000010 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00000100 - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM21 TRUE -#define STM32_TIM21_IS_32BITS FALSE -#define STM32_TIM21_CHANNELS 2 - -#define STM32_HAS_TIM22 TRUE -#define STM32_TIM22_IS_32BITS FALSE -#define STM32_TIM22_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00440000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x04004000 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART1 FALSE -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32L051xx, STM32L061xx. */ -/*===========================================================================*/ -#elif defined(STM32L051xx) || defined(STM32L061xx) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER TRUE -#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 FALSE -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0xFF840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIODEN | \ - RCC_IOPENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x06000600 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00600060 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00070000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00007000 - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000010 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00000100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_RX_DMA_CHN 0x00202000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI2_TX_DMA_CHN 0x02020000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM21 TRUE -#define STM32_TIM21_IS_32BITS FALSE -#define STM32_TIM21_CHANNELS 2 - -#define STM32_HAS_TIM22 TRUE -#define STM32_TIM22_IS_32BITS FALSE -#define STM32_TIM22_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00030300 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00003030 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00440000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x04004000 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - - -/*===========================================================================*/ -/* STM32L052xx, STM32L062xx, STM32L053xx, STM32L063xx. */ -/*===========================================================================*/ -#elif defined(STM32L052xx) || defined(STM32L062xx) || \ - defined(STM32L053xx) || defined(STM32L063xx) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER TRUE -#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_DAC1_CH1_DMA_CHN 0x00000090 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 TRUE -#define STM32_HAS_DAC2_CH2 TRUE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0xFF840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIODEN | \ - RCC_IOPENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x06000600 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00600060 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00070000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00007000 - -#define STM32_HAS_I2C3 FALSE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000010 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00000100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_RX_DMA_CHN 0x00202000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI2_TX_DMA_CHN 0x02020000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM21 TRUE -#define STM32_TIM21_IS_32BITS FALSE -#define STM32_TIM21_CHANNELS 2 - -#define STM32_HAS_TIM22 TRUE -#define STM32_TIM22_IS_32BITS FALSE -#define STM32_TIM22_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00030300 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00003030 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00440000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x04004000 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32L071xx. */ -/*===========================================================================*/ -#elif defined(STM32L071xx) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER TRUE -#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_DAC1_CH1_DMA_CHN 0x00000090 -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_DAC1_CH2_DMA_CHN 0x0000F000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0xFF840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIODEN | \ - RCC_IOPENR_GPIOEEN | \ - RCC_IOPENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x06000600 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00600060 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00070000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00007000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C3_RX_DMA_CHN 0x00E0E000 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C3_TX_DMA_CHN 0x0E0E0000 - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000010 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00000100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_RX_DMA_CHN 0x00202000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI2_TX_DMA_CHN 0x02020000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM21 TRUE -#define STM32_TIM21_IS_32BITS FALSE -#define STM32_TIM21_CHANNELS 2 - -#define STM32_HAS_TIM22 TRUE -#define STM32_TIM22_IS_32BITS FALSE -#define STM32_TIM22_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00030300 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00003030 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00440000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x04004000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_UART4_RX_DMA_CHN 0x00C000C0 -#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_UART4_TX_DMA_CHN 0x0C000C00 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_UART5_RX_DMA_CHN 0x00D000D0 -#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_UART5_TX_DMA_CHN 0x0D000D00 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/*===========================================================================*/ -/* STM32L072xx, STM32L073xx. */ -/*===========================================================================*/ -#elif defined(STM32L072xx) || defined(STM32L073xx) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC_SUPPORTS_PRESCALER TRUE -#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_DAC1_CH1_DMA_CHN 0x00000090 -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_DAC1_CH2_DMA_CHN 0x0000F000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 0 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 23 -#define STM32_EXTI_IMR1_MASK 0xFF840000U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ - RCC_IOPENR_GPIOBEN | \ - RCC_IOPENR_GPIOCEN | \ - RCC_IOPENR_GPIODEN | \ - RCC_IOPENR_GPIOEEN | \ - RCC_IOPENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_I2C1_RX_DMA_CHN 0x06000600 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x00600060 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_I2C2_RX_DMA_CHN 0x00070000 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C2_TX_DMA_CHN 0x00007000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C3_RX_DMA_CHN 0x00E0E000 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C3_TX_DMA_CHN 0x0E0E0000 - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000010 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_SPI1_TX_DMA_CHN 0x00000100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_SPI2_RX_DMA_CHN 0x00202000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI2_TX_DMA_CHN 0x02020000 - -#define STM32_HAS_SPI3 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM21 TRUE -#define STM32_TIM21_IS_32BITS FALSE -#define STM32_TIM21_CHANNELS 2 - -#define STM32_HAS_TIM22 TRUE -#define STM32_TIM22_IS_32BITS FALSE -#define STM32_TIM22_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00030300 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART1_TX_DMA_CHN 0x00003030 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00440000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x04004000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_UART4_RX_DMA_CHN 0x00C000C0 -#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_UART4_TX_DMA_CHN 0x0C000C00 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_UART5_RX_DMA_CHN 0x00D000D0 -#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_UART5_TX_DMA_CHN 0x0D000D00 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#else -#error "STM32L0xx device not specified" -#endif - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L0xx/stm32_registry.h + * @brief STM32L0xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32L0xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 20 +#define STM32_RTC_COMMON_HANDLER Vector48 +#define STM32_RTC_COMMON_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() \ + nvicEnableVector(STM32_RTC_COMMON_NUMBER, STM32_IRQ_EXTI17_20_PRIORITY) + +/*===========================================================================*/ +/* STM32L011xx. */ +/*===========================================================================*/ +#if defined(STM32L011xx) || defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER TRUE +#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 5 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0xFF840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x06000600 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00600060 + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000010 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00000100 + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM21 TRUE +#define STM32_TIM21_IS_32BITS FALSE +#define STM32_TIM21_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00440000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x04004000 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART1 FALSE +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32L031xx. */ +/*===========================================================================*/ +#elif defined(STM32L031xx) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER TRUE +#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0xFF840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x06000600 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00600060 + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000010 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00000100 + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM21 TRUE +#define STM32_TIM21_IS_32BITS FALSE +#define STM32_TIM21_CHANNELS 2 + +#define STM32_HAS_TIM22 TRUE +#define STM32_TIM22_IS_32BITS FALSE +#define STM32_TIM22_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM6 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00440000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x04004000 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART1 FALSE +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32L051xx, STM32L061xx. */ +/*===========================================================================*/ +#elif defined(STM32L051xx) || defined(STM32L061xx) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER TRUE +#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 FALSE +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0xFF840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIODEN | \ + RCC_IOPENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x06000600 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00600060 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00070000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00007000 + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000010 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00000100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_RX_DMA_CHN 0x00202000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI2_TX_DMA_CHN 0x02020000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM21 TRUE +#define STM32_TIM21_IS_32BITS FALSE +#define STM32_TIM21_CHANNELS 2 + +#define STM32_HAS_TIM22 TRUE +#define STM32_TIM22_IS_32BITS FALSE +#define STM32_TIM22_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00030300 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00003030 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00440000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x04004000 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + + +/*===========================================================================*/ +/* STM32L052xx, STM32L062xx, STM32L053xx, STM32L063xx. */ +/*===========================================================================*/ +#elif defined(STM32L052xx) || defined(STM32L062xx) || \ + defined(STM32L053xx) || defined(STM32L063xx) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER TRUE +#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_DAC1_CH1_DMA_CHN 0x00000090 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 TRUE +#define STM32_HAS_DAC2_CH2 TRUE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0xFF840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIODEN | \ + RCC_IOPENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x06000600 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00600060 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00070000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00007000 + +#define STM32_HAS_I2C3 FALSE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000010 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00000100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_RX_DMA_CHN 0x00202000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI2_TX_DMA_CHN 0x02020000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM21 TRUE +#define STM32_TIM21_IS_32BITS FALSE +#define STM32_TIM21_CHANNELS 2 + +#define STM32_HAS_TIM22 TRUE +#define STM32_TIM22_IS_32BITS FALSE +#define STM32_TIM22_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00030300 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00003030 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00440000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x04004000 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32L071xx. */ +/*===========================================================================*/ +#elif defined(STM32L071xx) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER TRUE +#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_DAC1_CH1_DMA_CHN 0x00000090 +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_DAC1_CH2_DMA_CHN 0x0000F000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0xFF840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIODEN | \ + RCC_IOPENR_GPIOEEN | \ + RCC_IOPENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x06000600 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00600060 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00070000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00007000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C3_RX_DMA_CHN 0x00E0E000 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C3_TX_DMA_CHN 0x0E0E0000 + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000010 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00000100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_RX_DMA_CHN 0x00202000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI2_TX_DMA_CHN 0x02020000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM21 TRUE +#define STM32_TIM21_IS_32BITS FALSE +#define STM32_TIM21_CHANNELS 2 + +#define STM32_HAS_TIM22 TRUE +#define STM32_TIM22_IS_32BITS FALSE +#define STM32_TIM22_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00030300 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00003030 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00440000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x04004000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_UART4_RX_DMA_CHN 0x00C000C0 +#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_UART4_TX_DMA_CHN 0x0C000C00 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_UART5_RX_DMA_CHN 0x00D000D0 +#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_UART5_TX_DMA_CHN 0x0D000D00 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/*===========================================================================*/ +/* STM32L072xx, STM32L073xx. */ +/*===========================================================================*/ +#elif defined(STM32L072xx) || defined(STM32L073xx) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC_SUPPORTS_PRESCALER TRUE +#define STM32_ADC_SUPPORTS_OVERSAMPLING TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_DAC1_CH1_DMA_CHN 0x00000090 +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_DAC1_CH2_DMA_CHN 0x0000F000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 0 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 23 +#define STM32_EXTI_IMR1_MASK 0xFF840000U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_IOPENR_GPIOAEN | \ + RCC_IOPENR_GPIOBEN | \ + RCC_IOPENR_GPIOCEN | \ + RCC_IOPENR_GPIODEN | \ + RCC_IOPENR_GPIOEEN | \ + RCC_IOPENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_I2C1_RX_DMA_CHN 0x06000600 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x00600060 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_I2C2_RX_DMA_CHN 0x00070000 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C2_TX_DMA_CHN 0x00007000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C3_RX_DMA_CHN 0x00E0E000 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C3_TX_DMA_CHN 0x0E0E0000 + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000010 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_SPI1_TX_DMA_CHN 0x00000100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_SPI2_RX_DMA_CHN 0x00202000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI2_TX_DMA_CHN 0x02020000 + +#define STM32_HAS_SPI3 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM21 TRUE +#define STM32_TIM21_IS_32BITS FALSE +#define STM32_TIM21_CHANNELS 2 + +#define STM32_HAS_TIM22 TRUE +#define STM32_TIM22_IS_32BITS FALSE +#define STM32_TIM22_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00030300 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART1_TX_DMA_CHN 0x00003030 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00440000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x04004000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_UART4_RX_DMA_CHN 0x00C000C0 +#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_UART4_TX_DMA_CHN 0x0C000C00 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_UART5_RX_DMA_CHN 0x00D000D0 +#define STM32_UART5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_UART5_TX_DMA_CHN 0x0D000D00 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#else +#error "STM32L0xx device not specified" +#endif + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c b/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c index 913f974f19..b61a73d206 100644 --- a/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c +++ b/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c @@ -1,294 +1,294 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/hal_adc_lld.c - * @brief STM32L1xx ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief ADC DMA ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - else if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -/** - * @brief ADC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector88) { - uint32_t sr; - - OSAL_IRQ_PROLOGUE(); - - sr = ADC1->SR; - ADC1->SR = 0; - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - if (ADCD1.grpp != NULL) - _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); - } - /* CHTODO: Add here analog watchdog handling.*/ - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = NULL; - ADCD1.dmamode = STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - - /* The shared vector is initialized on driver initialization and never - disabled.*/ - nvicEnableVector(ADC1_IRQn, STM32_ADC_IRQ_PRIORITY); -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(1, 1), - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); - - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - rccEnableADC1(true); - } -#endif /* STM32_ADC_USE_ADC1 */ - - ADC->CCR = (ADC->CCR & ADC_CCR_TSVREFE) | (STM32_ADC_ADCPRE << 16); - - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - adcp->adc->CR2 = ADC_CR2_ADON; - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - dmaStreamFreeI(adcp->dmastp); - adcp->dmastp = NULL; - - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC1(); -#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; - uint32_t cr2; - const ADCConversionGroup *grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - if (adcp->depth > 1) { - /* If circular buffer depth > 1, then the half transfer interrupt - is enabled in order to allow streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup.*/ - adcp->adc->SR = 0; - adcp->adc->SMPR1 = grpp->smpr1; - adcp->adc->SMPR2 = grpp->smpr2; - adcp->adc->SMPR3 = grpp->smpr3; - adcp->adc->SQR1 = grpp->sqr1; - adcp->adc->SQR2 = grpp->sqr2; - adcp->adc->SQR3 = grpp->sqr3; - adcp->adc->SQR4 = grpp->sqr4; - adcp->adc->SQR5 = grpp->sqr5; - - /* ADC configuration and start.*/ - adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; - - /* Enforcing the mandatory bits in CR2.*/ - cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; - - /* The start method is different dependign if HW or SW triggered, the - start is performed using the method specified in the CR2 configuration.*/ - if ((cr2 & ADC_CR2_SWSTART) != 0) { - /* Initializing CR2 while keeping ADC_CR2_SWSTART at zero.*/ - adcp->adc->CR2 = (cr2 | ADC_CR2_CONT) & ~ADC_CR2_SWSTART; - - /* Finally enabling ADC_CR2_SWSTART.*/ - adcp->adc->CR2 = (cr2 | ADC_CR2_CONT); - } - else - adcp->adc->CR2 = cr2; -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop_conversion(ADCDriver *adcp) { - - dmaStreamDisable(adcp->dmastp); - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - adcp->adc->CR2 = ADC_CR2_ADON; -} - -/** - * @brief Enables the TSVREFE bit. - * @details The TSVREFE bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - */ -void adcSTM32EnableTSVREFE(void) { - - ADC->CCR |= ADC_CCR_TSVREFE; -} - -/** - * @brief Disables the TSVREFE bit. - * @details The TSVREFE bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - */ -void adcSTM32DisableTSVREFE(void) { - - ADC->CCR &= ~ADC_CCR_TSVREFE; -} - -#endif /* HAL_USE_ADC */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/hal_adc_lld.c + * @brief STM32L1xx ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief ADC DMA ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + else if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +/** + * @brief ADC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector88) { + uint32_t sr; + + OSAL_IRQ_PROLOGUE(); + + sr = ADC1->SR; + ADC1->SR = 0; + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + if (ADCD1.grpp != NULL) + _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); + } + /* CHTODO: Add here analog watchdog handling.*/ + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = NULL; + ADCD1.dmamode = STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + + /* The shared vector is initialized on driver initialization and never + disabled.*/ + nvicEnableVector(ADC1_IRQn, STM32_ADC_IRQ_PRIORITY); +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + adcp->dmastp = dmaStreamAllocI(STM32_DMA_STREAM_ID(1, 1), + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream"); + + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + rccEnableADC1(true); + } +#endif /* STM32_ADC_USE_ADC1 */ + + ADC->CCR = (ADC->CCR & ADC_CCR_TSVREFE) | (STM32_ADC_ADCPRE << 16); + + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + adcp->adc->CR2 = ADC_CR2_ADON; + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + dmaStreamFreeI(adcp->dmastp); + adcp->dmastp = NULL; + + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC1(); +#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; + uint32_t cr2; + const ADCConversionGroup *grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + if (adcp->depth > 1) { + /* If circular buffer depth > 1, then the half transfer interrupt + is enabled in order to allow streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup.*/ + adcp->adc->SR = 0; + adcp->adc->SMPR1 = grpp->smpr1; + adcp->adc->SMPR2 = grpp->smpr2; + adcp->adc->SMPR3 = grpp->smpr3; + adcp->adc->SQR1 = grpp->sqr1; + adcp->adc->SQR2 = grpp->sqr2; + adcp->adc->SQR3 = grpp->sqr3; + adcp->adc->SQR4 = grpp->sqr4; + adcp->adc->SQR5 = grpp->sqr5; + + /* ADC configuration and start.*/ + adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; + + /* Enforcing the mandatory bits in CR2.*/ + cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON; + + /* The start method is different dependign if HW or SW triggered, the + start is performed using the method specified in the CR2 configuration.*/ + if ((cr2 & ADC_CR2_SWSTART) != 0) { + /* Initializing CR2 while keeping ADC_CR2_SWSTART at zero.*/ + adcp->adc->CR2 = (cr2 | ADC_CR2_CONT) & ~ADC_CR2_SWSTART; + + /* Finally enabling ADC_CR2_SWSTART.*/ + adcp->adc->CR2 = (cr2 | ADC_CR2_CONT); + } + else + adcp->adc->CR2 = cr2; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + + dmaStreamDisable(adcp->dmastp); + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + adcp->adc->CR2 = ADC_CR2_ADON; +} + +/** + * @brief Enables the TSVREFE bit. + * @details The TSVREFE bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + */ +void adcSTM32EnableTSVREFE(void) { + + ADC->CCR |= ADC_CCR_TSVREFE; +} + +/** + * @brief Disables the TSVREFE bit. + * @details The TSVREFE bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + */ +void adcSTM32DisableTSVREFE(void) { + + ADC->CCR &= ~ADC_CCR_TSVREFE; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.h b/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.h index 31f8679bac..091e06f968 100644 --- a/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.h +++ b/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.h @@ -1,383 +1,383 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/hal_adc_lld.h - * @brief STM32L1xx ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef HAL_ADC_LLD_H -#define HAL_ADC_LLD_H - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Triggers selection - * @{ - */ -#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */ -/** @} */ - -/** - * @name ADC clock divider settings - * @{ - */ -#define ADC_CCR_ADCPRE_DIV1 0 -#define ADC_CCR_ADCPRE_DIV2 1 -#define ADC_CCR_ADCPRE_DIV4 2 -/** @} */ - -/** - * @name Available analog channels - * @{ - */ -#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ -#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ -#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ -#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ -#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ -#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ -#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ -#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ -#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ -#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ -#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ -#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ -#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ -#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ -#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ -#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ -#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/ -#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ -#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */ -#define ADC_CHANNEL_IN19 19 /**< @brief External analog input 19. */ -#define ADC_CHANNEL_IN20 20 /**< @brief External analog input 20. */ -#define ADC_CHANNEL_IN21 21 /**< @brief External analog input 21. */ -#define ADC_CHANNEL_IN22 22 /**< @brief External analog input 22. */ -#define ADC_CHANNEL_IN23 23 /**< @brief External analog input 23. */ -#define ADC_CHANNEL_IN24 24 /**< @brief External analog input 24. */ -#define ADC_CHANNEL_IN25 25 /**< @brief External analog input 25. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SAMPLE_4 0 /**< @brief 4 cycles sampling time. */ -#define ADC_SAMPLE_9 1 /**< @brief 9 cycles sampling time. */ -#define ADC_SAMPLE_16 2 /**< @brief 16 cycles sampling time. */ -#define ADC_SAMPLE_24 3 /**< @brief 24 cycles sampling time. */ -#define ADC_SAMPLE_48 4 /**< @brief 48 cycles sampling time. */ -#define ADC_SAMPLE_96 5 /**< @brief 96 cycles sampling time. */ -#define ADC_SAMPLE_192 6 /**< @brief 192 cycles sampling time. */ -#define ADC_SAMPLE_384 7 /**< @brief 384 cycles sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC common clock divider. - * @note This setting is influenced by the VDDA voltage and other - * external conditions, please refer to the STM32L15x datasheet - * for more info.
- * See section 6.3.15 "12-bit ADC characteristics". - */ -#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV1 -#endif - -/** - * @brief ADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - */ -#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC1 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#endif - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC1 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/** - * * @brief ADC frequency. - * */ -/* ADC clock related settings and checks.*/ -#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV1 -#define STM32_ADCCLK STM32_HSICLK -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2 -#define STM32_ADCCLK (STM32_HSICLK / 2) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4 -#define STM32_ADCCLK (STM32_HSICLK / 4) -#else -#error "invalid STM32_ADC_ADCPRE value specified" -#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; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the ADC driver structure. - */ -#define adc_lld_driver_fields \ - /* Pointer to the ADCx registers block.*/ \ - ADC_TypeDef *adc; \ - /* Pointer to associated DMA channel.*/ \ - const stm32_dma_stream_t *dmastp; \ - /* DMA mode bit mask.*/ \ - uint32_t dmamode - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/** - * @brief Low level fields of the ADC configuration structure. - */ -#define adc_lld_configuration_group_fields \ - /* 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; \ - /* 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; \ - /* ADC SMPR1 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 20...25.*/ \ - uint32_t smpr1; \ - /* ADC SMPR2 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 10...19.*/ \ - uint32_t smpr2; \ - /* ADC SMPR3 register initialization data. \ - NOTE: In this field must be specified the sample times for channels \ - 0...9.*/ \ - uint32_t smpr3; \ - /* ADC SQR1 register initialization data. \ - NOTE: Conversion group sequence 25...27 + sequence length.*/ \ - uint32_t sqr1; \ - /* ADC SQR2 register initialization data. \ - NOTE: Conversion group sequence 19...24.*/ \ - uint32_t sqr2; \ - /* ADC SQR3 register initialization data. \ - NOTE: Conversion group sequence 13...18.*/ \ - uint32_t sqr3; \ - /* ADC SQR3 register initialization data. \ - NOTE: Conversion group sequence 7...12.*/ \ - uint32_t sqr4; \ - /* ADC SQR3 register initialization data. \ - NOTE: Conversion group sequence 1...6.*/ \ - uint32_t sqr5 - -/** - * @name Sequences building helper macros - * @{ - */ -/** - * @brief Number of channels in a conversion sequence. - */ -#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) - -#define ADC_SQR5_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */ -#define ADC_SQR5_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */ -#define ADC_SQR5_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */ -#define ADC_SQR5_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */ -#define ADC_SQR5_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */ -#define ADC_SQR5_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */ - -#define ADC_SQR4_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */ -#define ADC_SQR4_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */ -#define ADC_SQR4_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */ -#define ADC_SQR4_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/ -#define ADC_SQR4_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/ -#define ADC_SQR4_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/ - -#define ADC_SQR3_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/ -#define ADC_SQR3_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/ -#define ADC_SQR3_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/ -#define ADC_SQR3_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/ -#define ADC_SQR3_SQ17_N(n) ((n) << 20) /**< @brief 17th channel in seq.*/ -#define ADC_SQR3_SQ18_N(n) ((n) << 25) /**< @brief 18th channel in seq.*/ - -#define ADC_SQR2_SQ19_N(n) ((n) << 0) /**< @brief 19th channel in seq.*/ -#define ADC_SQR2_SQ20_N(n) ((n) << 5) /**< @brief 20th channel in seq.*/ -#define ADC_SQR2_SQ21_N(n) ((n) << 10) /**< @brief 21th channel in seq.*/ -#define ADC_SQR2_SQ22_N(n) ((n) << 15) /**< @brief 22th channel in seq.*/ -#define ADC_SQR2_SQ23_N(n) ((n) << 20) /**< @brief 23th channel in seq.*/ -#define ADC_SQR2_SQ24_N(n) ((n) << 25) /**< @brief 24th channel in seq.*/ - -#define ADC_SQR1_SQ25_N(n) ((n) << 0) /**< @brief 25th channel in seq.*/ -#define ADC_SQR1_SQ26_N(n) ((n) << 5) /**< @brief 26th channel in seq.*/ -#define ADC_SQR1_SQ27_N(n) ((n) << 10) /**< @brief 27th channel in seq.*/ -/** @} */ - -/** - * @name Sampling rate settings helper macros - * @{ - */ -#define ADC_SMPR3_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */ -#define ADC_SMPR3_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ -#define ADC_SMPR3_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ -#define ADC_SMPR3_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ -#define ADC_SMPR3_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ -#define ADC_SMPR3_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ -#define ADC_SMPR3_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ -#define ADC_SMPR3_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ -#define ADC_SMPR3_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ -#define ADC_SMPR3_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ - -#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ -#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ -#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ -#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ -#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ -#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ -#define ADC_SMPR2_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor - sampling time. */ -#define ADC_SMPR2_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference - sampling time. */ -#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 sampling time. */ -#define ADC_SMPR2_SMP_AN19(n) ((n) << 27) /**< @brief AN19 sampling time. */ - -#define ADC_SMPR1_SMP_AN20(n) ((n) << 0) /**< @brief AN20 sampling time. */ -#define ADC_SMPR1_SMP_AN21(n) ((n) << 3) /**< @brief AN21 sampling time. */ -#define ADC_SMPR1_SMP_AN22(n) ((n) << 6) /**< @brief AN22 sampling time. */ -#define ADC_SMPR1_SMP_AN23(n) ((n) << 9) /**< @brief AN23 sampling time. */ -#define ADC_SMPR1_SMP_AN24(n) ((n) << 12) /**< @brief AN24 sampling time. */ -#define ADC_SMPR1_SMP_AN25(n) ((n) << 15) /**< @brief AN25 sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); - void adcSTM32EnableTSVREFE(void); - void adcSTM32DisableTSVREFE(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* HAL_ADC_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/hal_adc_lld.h + * @brief STM32L1xx ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Triggers selection + * @{ + */ +#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */ +/** @} */ + +/** + * @name ADC clock divider settings + * @{ + */ +#define ADC_CCR_ADCPRE_DIV1 0 +#define ADC_CCR_ADCPRE_DIV2 1 +#define ADC_CCR_ADCPRE_DIV4 2 +/** @} */ + +/** + * @name Available analog channels + * @{ + */ +#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ +#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ +#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ +#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ +#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ +#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ +#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ +#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ +#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ +#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ +#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ +#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ +#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ +#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ +#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ +#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ +#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/ +#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ +#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */ +#define ADC_CHANNEL_IN19 19 /**< @brief External analog input 19. */ +#define ADC_CHANNEL_IN20 20 /**< @brief External analog input 20. */ +#define ADC_CHANNEL_IN21 21 /**< @brief External analog input 21. */ +#define ADC_CHANNEL_IN22 22 /**< @brief External analog input 22. */ +#define ADC_CHANNEL_IN23 23 /**< @brief External analog input 23. */ +#define ADC_CHANNEL_IN24 24 /**< @brief External analog input 24. */ +#define ADC_CHANNEL_IN25 25 /**< @brief External analog input 25. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SAMPLE_4 0 /**< @brief 4 cycles sampling time. */ +#define ADC_SAMPLE_9 1 /**< @brief 9 cycles sampling time. */ +#define ADC_SAMPLE_16 2 /**< @brief 16 cycles sampling time. */ +#define ADC_SAMPLE_24 3 /**< @brief 24 cycles sampling time. */ +#define ADC_SAMPLE_48 4 /**< @brief 48 cycles sampling time. */ +#define ADC_SAMPLE_96 5 /**< @brief 96 cycles sampling time. */ +#define ADC_SAMPLE_192 6 /**< @brief 192 cycles sampling time. */ +#define ADC_SAMPLE_384 7 /**< @brief 384 cycles sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC common clock divider. + * @note This setting is influenced by the VDDA voltage and other + * external conditions, please refer to the STM32L15x datasheet + * for more info.
+ * See section 6.3.15 "12-bit ADC characteristics". + */ +#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV1 +#endif + +/** + * @brief ADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + */ +#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC1 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC1 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/** + * * @brief ADC frequency. + * */ +/* ADC clock related settings and checks.*/ +#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV1 +#define STM32_ADCCLK STM32_HSICLK +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2 +#define STM32_ADCCLK (STM32_HSICLK / 2) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4 +#define STM32_ADCCLK (STM32_HSICLK / 4) +#else +#error "invalid STM32_ADC_ADCPRE value specified" +#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; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADCx registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const stm32_dma_stream_t *dmastp; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_configuration_group_fields \ + /* 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; \ + /* 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; \ + /* ADC SMPR1 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 20...25.*/ \ + uint32_t smpr1; \ + /* ADC SMPR2 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 10...19.*/ \ + uint32_t smpr2; \ + /* ADC SMPR3 register initialization data. \ + NOTE: In this field must be specified the sample times for channels \ + 0...9.*/ \ + uint32_t smpr3; \ + /* ADC SQR1 register initialization data. \ + NOTE: Conversion group sequence 25...27 + sequence length.*/ \ + uint32_t sqr1; \ + /* ADC SQR2 register initialization data. \ + NOTE: Conversion group sequence 19...24.*/ \ + uint32_t sqr2; \ + /* ADC SQR3 register initialization data. \ + NOTE: Conversion group sequence 13...18.*/ \ + uint32_t sqr3; \ + /* ADC SQR3 register initialization data. \ + NOTE: Conversion group sequence 7...12.*/ \ + uint32_t sqr4; \ + /* ADC SQR3 register initialization data. \ + NOTE: Conversion group sequence 1...6.*/ \ + uint32_t sqr5 + +/** + * @name Sequences building helper macros + * @{ + */ +/** + * @brief Number of channels in a conversion sequence. + */ +#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) + +#define ADC_SQR5_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */ +#define ADC_SQR5_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */ +#define ADC_SQR5_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */ +#define ADC_SQR5_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */ +#define ADC_SQR5_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */ +#define ADC_SQR5_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */ + +#define ADC_SQR4_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */ +#define ADC_SQR4_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */ +#define ADC_SQR4_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */ +#define ADC_SQR4_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/ +#define ADC_SQR4_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/ +#define ADC_SQR4_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/ + +#define ADC_SQR3_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/ +#define ADC_SQR3_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/ +#define ADC_SQR3_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/ +#define ADC_SQR3_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/ +#define ADC_SQR3_SQ17_N(n) ((n) << 20) /**< @brief 17th channel in seq.*/ +#define ADC_SQR3_SQ18_N(n) ((n) << 25) /**< @brief 18th channel in seq.*/ + +#define ADC_SQR2_SQ19_N(n) ((n) << 0) /**< @brief 19th channel in seq.*/ +#define ADC_SQR2_SQ20_N(n) ((n) << 5) /**< @brief 20th channel in seq.*/ +#define ADC_SQR2_SQ21_N(n) ((n) << 10) /**< @brief 21th channel in seq.*/ +#define ADC_SQR2_SQ22_N(n) ((n) << 15) /**< @brief 22th channel in seq.*/ +#define ADC_SQR2_SQ23_N(n) ((n) << 20) /**< @brief 23th channel in seq.*/ +#define ADC_SQR2_SQ24_N(n) ((n) << 25) /**< @brief 24th channel in seq.*/ + +#define ADC_SQR1_SQ25_N(n) ((n) << 0) /**< @brief 25th channel in seq.*/ +#define ADC_SQR1_SQ26_N(n) ((n) << 5) /**< @brief 26th channel in seq.*/ +#define ADC_SQR1_SQ27_N(n) ((n) << 10) /**< @brief 27th channel in seq.*/ +/** @} */ + +/** + * @name Sampling rate settings helper macros + * @{ + */ +#define ADC_SMPR3_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */ +#define ADC_SMPR3_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ +#define ADC_SMPR3_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ +#define ADC_SMPR3_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ +#define ADC_SMPR3_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ +#define ADC_SMPR3_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ +#define ADC_SMPR3_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ +#define ADC_SMPR3_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ +#define ADC_SMPR3_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ +#define ADC_SMPR3_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ + +#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ +#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ +#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ +#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ +#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ +#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ +#define ADC_SMPR2_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor + sampling time. */ +#define ADC_SMPR2_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference + sampling time. */ +#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 sampling time. */ +#define ADC_SMPR2_SMP_AN19(n) ((n) << 27) /**< @brief AN19 sampling time. */ + +#define ADC_SMPR1_SMP_AN20(n) ((n) << 0) /**< @brief AN20 sampling time. */ +#define ADC_SMPR1_SMP_AN21(n) ((n) << 3) /**< @brief AN21 sampling time. */ +#define ADC_SMPR1_SMP_AN22(n) ((n) << 6) /**< @brief AN22 sampling time. */ +#define ADC_SMPR1_SMP_AN23(n) ((n) << 9) /**< @brief AN23 sampling time. */ +#define ADC_SMPR1_SMP_AN24(n) ((n) << 12) /**< @brief AN24 sampling time. */ +#define ADC_SMPR1_SMP_AN25(n) ((n) << 15) /**< @brief AN25 sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); + void adcSTM32EnableTSVREFE(void); + void adcSTM32DisableTSVREFE(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/hal_lld.c b/os/hal/ports/STM32/STM32L1xx/hal_lld.c index 9731411837..10e34bc295 100644 --- a/os/hal/ports/STM32/STM32L1xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32L1xx/hal_lld.c @@ -1,244 +1,245 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/hal_lld.c - * @brief STM32L1xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -/* CHTODO: LSEBYP like in F3.*/ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32l1xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->CSR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->CSR |= RCC_CSR_RTCRST; - RCC->CSR &= ~RCC_CSR_RTCRST; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - /* Waits until LSE is stable or times out. */ - RCC->CSR |= RCC_CSR_LSEON; - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->CSR & RCC_CSR_LSERDY) == 0) - ; -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->CSR & RCC_CSR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->CSR |= (RCC->CSR & RCC_CSR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->CSR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->CSR |= RCC_CSR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB(~(RCC_AHBRSTR_FLITFRST | STM32_GPIO_EN_MASK)); - rccResetAPB1(~RCC_APB1RSTR_PWRRST); - rccResetAPB2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32L1xx voltage, clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -/** - * @brief Clocks and internal voltage initialization. - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ - RCC->APB1ENR = RCC_APB1ENR_PWREN; - - /* Core voltage setup.*/ - while ((PWR->CSR & PWR_CSR_VOSF) != 0) - ; /* Waits until regulator is stable. */ - PWR->CR = STM32_VOS; - while ((PWR->CSR & PWR_CSR_VOSF) != 0) - ; /* Waits until regulator is stable. */ - - /* Initial clocks setup and wait for MSI stabilization, the MSI clock is - always enabled because it is the fallback clock when PLL the fails. - Trim fields are not altered from reset values.*/ - RCC->CFGR = 0; - RCC->ICSCR = (RCC->ICSCR & ~STM32_MSIRANGE_MASK) | STM32_MSIRANGE; - RCC->CR = RCC_CR_MSION; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; /* Waits until MSI is stable. */ - -#if STM32_HSI_ENABLED - /* HSI activation.*/ - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Waits until HSI is stable. */ -#endif - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - -#if STM32_LSE_ENABLED - /* LSE activation, have to unlock the register.*/ - if ((RCC->CSR & RCC_CSR_LSEON) == 0) { - PWR->CR |= PWR_CR_DBP; - RCC->CSR |= RCC_CSR_LSEON; - PWR->CR &= ~PWR_CR_DBP; - } - while ((RCC->CSR & RCC_CSR_LSERDY) == 0) - ; /* Waits until LSE is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CFGR |= STM32_PLLDIV | STM32_PLLMUL | STM32_PLLSRC; - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CR |= STM32_RTCPRE; - RCC->CFGR |= STM32_MCOPRE | STM32_MCOSEL | - STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - RCC->CSR |= STM32_RTCSEL; - - /* Flash setup and final clock selection.*/ -#if defined(STM32_FLASHBITS1) - FLASH->ACR = STM32_FLASHBITS1; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS1 & FLASH_ACR_LATENCY_Msk)) { - } -#endif -#if defined(STM32_FLASHBITS2) - FLASH->ACR = STM32_FLASHBITS2; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS2 & FLASH_ACR_LATENCY_Msk)) { - } -#endif - - /* Switching to the configured clock source if it is different from MSI.*/ -#if (STM32_SW != STM32_SW_MSI) - 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); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/hal_lld.c + * @brief STM32L1xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +/* CHTODO: LSEBYP like in F3.*/ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32l1xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if (((RCC->CSR & STM32_RTCSEL_MASK) != STM32_RTCSEL) + && ((RCC->CSR & STM32_RTCSEL_MASK) != FOME_STM32_LSE_WAIT_MAX_RTCSEL)) { + /* Backup domain reset.*/ + RCC->CSR |= RCC_CSR_RTCRST; + RCC->CSR &= ~RCC_CSR_RTCRST; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED + int fomeLseCounter = 0; + /* Waits until LSE is stable or times out. */ + RCC->CSR |= RCC_CSR_LSEON; + while ((!FOME_STM32_LSE_WAIT_MAX || fomeLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->CSR & RCC_CSR_LSERDY) == 0) + ; +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->CSR & RCC_CSR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->CSR |= (RCC->CSR & RCC_CSR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->CSR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->CSR |= RCC_CSR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB(~(RCC_AHBRSTR_FLITFRST | STM32_GPIO_EN_MASK)); + rccResetAPB1(~RCC_APB1RSTR_PWRRST); + rccResetAPB2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32L1xx voltage, clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +/** + * @brief Clocks and internal voltage initialization. + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ + RCC->APB1ENR = RCC_APB1ENR_PWREN; + + /* Core voltage setup.*/ + while ((PWR->CSR & PWR_CSR_VOSF) != 0) + ; /* Waits until regulator is stable. */ + PWR->CR = STM32_VOS; + while ((PWR->CSR & PWR_CSR_VOSF) != 0) + ; /* Waits until regulator is stable. */ + + /* Initial clocks setup and wait for MSI stabilization, the MSI clock is + always enabled because it is the fallback clock when PLL the fails. + Trim fields are not altered from reset values.*/ + RCC->CFGR = 0; + RCC->ICSCR = (RCC->ICSCR & ~STM32_MSIRANGE_MASK) | STM32_MSIRANGE; + RCC->CR = RCC_CR_MSION; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; /* Waits until MSI is stable. */ + +#if STM32_HSI_ENABLED + /* HSI activation.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Waits until HSI is stable. */ +#endif + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + +#if STM32_LSE_ENABLED + /* LSE activation, have to unlock the register.*/ + if ((RCC->CSR & RCC_CSR_LSEON) == 0) { + PWR->CR |= PWR_CR_DBP; + RCC->CSR |= RCC_CSR_LSEON; + PWR->CR &= ~PWR_CR_DBP; + } + while ((RCC->CSR & RCC_CSR_LSERDY) == 0) + ; /* Waits until LSE is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CFGR |= STM32_PLLDIV | STM32_PLLMUL | STM32_PLLSRC; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CR |= STM32_RTCPRE; + RCC->CFGR |= STM32_MCOPRE | STM32_MCOSEL | + STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + RCC->CSR |= STM32_RTCSEL; + + /* Flash setup and final clock selection.*/ +#if defined(STM32_FLASHBITS1) + FLASH->ACR = STM32_FLASHBITS1; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS1 & FLASH_ACR_LATENCY_Msk)) { + } +#endif +#if defined(STM32_FLASHBITS2) + FLASH->ACR = STM32_FLASHBITS2; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS2 & FLASH_ACR_LATENCY_Msk)) { + } +#endif + + /* Switching to the configured clock source if it is different from MSI.*/ +#if (STM32_SW != STM32_SW_MSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/hal_lld.h b/os/hal/ports/STM32/STM32L1xx/hal_lld.h index 28ed1bf165..20ca952f99 100644 --- a/os/hal/ports/STM32/STM32L1xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32L1xx/hal_lld.h @@ -1,882 +1,891 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/hal_lld.h - * @brief STM32L1xx 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_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32L100xB, STM32L100xBA, STM32L100xC. - * - STM32L151xB, STM32L151xBA, STM32L151xC, STM32L151xCA, - * STM32L151xD, STM32L151xDX, STM32L151xE. - * - STM32L152xB, STM32L152xBA, STM32L152xC, STM32L152xCA, - * STM32L152xD, STM32L152xDX, STM32L152xE. - * - STM32L162xC, STM32L162xCA, STM32L162xD, STM32L162xDX, - * STM32L162xE. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32L100xB) || defined(STM32L151xB) || \ - defined(STM32L152xB) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32L1xx Ultra Low Power Medium Density" - -#elif defined(STM32L100xBA) || defined(STM32L100xC) || \ - defined(STM32L151xBA) || defined(STM32L151xC) || \ - defined(STM32L151xCA) || defined(STM32L152xBA) || \ - defined(STM32L152xC) || defined(STM32L152xCA) || \ - defined(STM32L162xC) || defined(STM32L162xCA) -#define PLATFORM_NAME "STM32L1xx Ultra Low Power Medium Density Plus" - -#elif defined(STM32L151xD) || defined(STM32L151xDX) || \ - defined(STM32L151xE) || defined(STM32L152xD) || \ - defined(STM32L152xDX) || defined(STM32L152xE) || \ - defined(STM32L162xD) || defined(STM32L162xDX) || \ - defined(STM32L162xE) -#define PLATFORM_NAME "STM32L1xx Ultra Low Power High Density" - -#else -#error "STM32L1xx device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32L1XX) || defined(__DOXYGEN__) -#define STM32L1XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 16000000 /**< High speed internal clock. */ -#define STM32_LSICLK 38000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_VOS_MASK (3 << 11) /**< Core voltage mask. */ -#define STM32_VOS_1P8 (1 << 11) /**< Core voltage 1.8 Volts. */ -#define STM32_VOS_1P5 (2 << 11) /**< Core voltage 1.5 Volts. */ -#define STM32_VOS_1P2 (3 << 11) /**< Core voltage 1.2 Volts. */ - -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CR register bits definitions - * @{ - */ -#define STM32_RTCPRE_MASK (3 << 29) /**< RTCPRE mask. */ -#define STM32_RTCPRE_DIV2 (0 << 29) /**< HSE divided by 2. */ -#define STM32_RTCPRE_DIV4 (1 << 29) /**< HSE divided by 4. */ -#define STM32_RTCPRE_DIV8 (2 << 29) /**< HSE divided by 2. */ -#define STM32_RTCPRE_DIV16 (3 << 29) /**< HSE divided by 16. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ -#define STM32_SW_HSI (1 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (2 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_MSI (3 << 24) /**< MSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ - -#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ -#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ -#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ -#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ -#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ -/** @} */ - -/** - * @name RCC_ICSCR register bits definitions - * @{ - */ -#define STM32_MSIRANGE_MASK (7 << 13) /**< MSIRANGE field mask. */ -#define STM32_MSIRANGE_64K (0 << 13) /**< 64kHz nominal. */ -#define STM32_MSIRANGE_128K (1 << 13) /**< 128kHz nominal. */ -#define STM32_MSIRANGE_256K (2 << 13) /**< 256kHz nominal. */ -#define STM32_MSIRANGE_512K (3 << 13) /**< 512kHz nominal. */ -#define STM32_MSIRANGE_1M (4 << 13) /**< 1MHz nominal. */ -#define STM32_MSIRANGE_2M (5 << 13) /**< 2MHz nominal. */ -#define STM32_MSIRANGE_4M (6 << 13) /**< 4MHz nominal */ -/** @} */ - -/** - * @name RCC_CSR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 16) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 16) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1 << 16) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2 << 16) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3 << 16) /**< RTC source is HSE divided. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_1P8 -#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. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#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 -#endif - -/** - * @brief MSI frequency setting. - */ -#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) -#define STM32_MSIRANGE STM32_MSIRANGE_2M -#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. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSI -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed values are 3, 4, 6, 8, 12, 16, 32, 48. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 6 -#endif - -/** - * @brief PLL divider value. - * @note The allowed values are 2, 3, 4. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_PLLDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLDIV_VALUE 3 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 32MHz system clock from - * the internal 16MHz HSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief RTC/LCD clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief HSE divider toward RTC setting. - */ -#if !defined(STM32_RTCPRE) || defined(__DOXYGEN__) -#define STM32_RTCPRE STM32_RTCPRE_DIV2 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32L1xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L1xx_MCUCONF not defined" -#endif - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_1P8) || defined(__DOXYGEN__) -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @brief Maximum SYSCLK clock frequency at current voltage setting. - */ -#define STM32_SYSCLK_MAX 32000000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 96000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 6000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 32000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 32000000 - -/** - * @brief Maximum frequency not requiring a wait state for flash accesses. - */ -#define STM32_0WS_THRESHOLD 16000000 - -/** - * @brief HSI availability at current voltage settings. - */ -#define STM32_HSI_AVAILABLE TRUE - -#elif STM32_VOS == STM32_VOS_1P5 -#define STM32_HSECLK_MAX 16000000 -#define STM32_SYSCLK_MAX 16000000 -#define STM32_PLLVCO_MAX 48000000 -#define STM32_PLLVCO_MIN 6000000 -#define STM32_PCLK1_MAX 16000000 -#define STM32_PCLK2_MAX 16000000 -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_HSI_AVAILABLE TRUE -#elif STM32_VOS == STM32_VOS_1P2 -#define STM32_HSECLK_MAX 4000000 -#define STM32_SYSCLK_MAX 4000000 -#define STM32_PLLVCO_MAX 24000000 -#define STM32_PLLVCO_MIN 6000000 -#define STM32_PCLK1_MAX 4000000 -#define STM32_PCLK2_MAX 4000000 -#define STM32_0WS_THRESHOLD 2000000 -#define STM32_HSI_AVAILABLE FALSE -#else -#error "invalid STM32_VOS value specified" -#endif - -/* HSI related checks.*/ -#if STM32_HSI_ENABLED -#if !STM32_HSI_AVAILABLE - #error "impossible to activate HSI under the current voltage settings" -#endif -#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_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "required HSI clock is not enabled" -#endif -#endif /* !STM32_HSI_ENABLED */ - -/* 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)" -#endif -#else /* !STM32_HSE_ENABLED */ -#if (STM32_SW == STM32_SW_HSE) || \ - ((STM32_SW == STM32_SW_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ - (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ - (STM32_RTCSEL == STM32_RTCSEL_HSEDIV) -#error "required HSE clock is not enabled" -#endif -#endif /* !STM32_HSE_ENABLED */ - -/* LSI related checks.*/ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_LSI -#error "LSI not enabled, required by STM32_MCOSEL" -#endif - -#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* LSE related checks.*/ -#if STM32_LSE_ENABLED -#if (STM32_LSECLK == 0) -#error "impossible to activate LSE" -#endif -#if (STM32_LSECLK < 1000) || (STM32_LSECLK > 1000000) -#error "STM32_LSECLK outside acceptable range (1...1000kHz)" -#endif -#else /* !STM32_LSE_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_LSE -#error "LSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL related checks.*/ -#if STM32_USB_CLOCK_ENABLED || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief PLLMUL field. - */ -#if (STM32_PLLMUL_VALUE == 3) || defined(__DOXYGEN__) -#define STM32_PLLMUL (0 << 18) -#elif STM32_PLLMUL_VALUE == 4 -#define STM32_PLLMUL (1 << 18) -#elif STM32_PLLMUL_VALUE == 6 -#define STM32_PLLMUL (2 << 18) -#elif STM32_PLLMUL_VALUE == 8 -#define STM32_PLLMUL (3 << 18) -#elif STM32_PLLMUL_VALUE == 12 -#define STM32_PLLMUL (4 << 18) -#elif STM32_PLLMUL_VALUE == 16 -#define STM32_PLLMUL (5 << 18) -#elif STM32_PLLMUL_VALUE == 24 -#define STM32_PLLMUL (6 << 18) -#elif STM32_PLLMUL_VALUE == 32 -#define STM32_PLLMUL (7 << 18) -#elif STM32_PLLMUL_VALUE == 48 -#define STM32_PLLMUL (8 << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLLDIV field. - */ -#if (STM32_PLLDIV_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLDIV (1 << 22) -#elif STM32_PLLDIV_VALUE == 3 -#define STM32_PLLDIV (2 << 22) -#elif STM32_PLLDIV_VALUE == 4 -#define STM32_PLLDIV (3 << 22) -#else -#error "invalid STM32_PLLDIV_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 < 2000000) || (STM32_PLLCLKIN > 24000000) -#error "STM32_PLLCLKIN outside acceptable range (2...24MHz)" -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLDIV_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < 2000000) || (STM32_PLLCLKOUT > 32000000) -#error "STM32_PLLCLKOUT outside acceptable range (2...32MHz)" -#endif - -/** - * @brief MSI frequency. - */ -#if STM32_MSIRANGE == STM32_MSIRANGE_64K -#define STM32_MSICLK 65500 -#elif STM32_MSIRANGE == STM32_MSIRANGE_128K -#define STM32_MSICLK 131000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_256K -#define STM32_MSICLK 262000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_512K -#define STM32_MSICLK 524000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_1M -#define STM32_MSICLK 1050000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_2M -#define STM32_MSICLK 2100000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_4M -#define STM32_MSICLK 4200000 -#else -#error "invalid STM32_MSIRANGE value specified" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK 2100000 -#elif (STM32_SW == STM32_SW_MSI) -#define STM32_SYSCLK STM32_MSICLK -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief MCO clock before divider. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 -#elif STM32_MCOSEL == STM32_MCOSEL_HSI -#define STM32_MCODIVCLK STM32_HSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_MSI -#define STM32_MCODIVCLK STM32_MSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK -#elif STM32_MCOSEL == STM32_MCOSEL_PLL -#define STM32_MCODIVCLK STM32_PLLCLKOUT -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief HSE divider toward RTC clock. - */ -#if (STM32_RTCPRE == STM32_RTCPRE_DIV2) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 2) -#elif (STM32_RTCPRE == STM32_RTCPRE_DIV4) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 4) -#elif (STM32_RTCPRE == STM32_RTCPRE_DIV8) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 8) -#elif (STM32_RTCPRE == STM32_RTCPRE_DIV16) || defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / 16) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief RTC/LCD clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK STM32_HSEDIVCLK -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USB frequency. - */ -#define STM32_USBCLK (STM32_PLLVCO / 2) - -/** - * @brief Timers 2, 3, 4, 6, 7 clock. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 9, 10, 11 clock. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS1 0x00000000 -#else -#define STM32_FLASHBITS1 0x00000004 -#define STM32_FLASHBITS2 0x00000007 -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/hal_lld.h + * @brief STM32L1xx 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_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32L100xB, STM32L100xBA, STM32L100xC. + * - STM32L151xB, STM32L151xBA, STM32L151xC, STM32L151xCA, + * STM32L151xD, STM32L151xDX, STM32L151xE. + * - STM32L152xB, STM32L152xBA, STM32L152xC, STM32L152xCA, + * STM32L152xD, STM32L152xDX, STM32L152xE. + * - STM32L162xC, STM32L162xCA, STM32L162xD, STM32L162xDX, + * STM32L162xE. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32L100xB) || defined(STM32L151xB) || \ + defined(STM32L152xB) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32L1xx Ultra Low Power Medium Density" + +#elif defined(STM32L100xBA) || defined(STM32L100xC) || \ + defined(STM32L151xBA) || defined(STM32L151xC) || \ + defined(STM32L151xCA) || defined(STM32L152xBA) || \ + defined(STM32L152xC) || defined(STM32L152xCA) || \ + defined(STM32L162xC) || defined(STM32L162xCA) +#define PLATFORM_NAME "STM32L1xx Ultra Low Power Medium Density Plus" + +#elif defined(STM32L151xD) || defined(STM32L151xDX) || \ + defined(STM32L151xE) || defined(STM32L152xD) || \ + defined(STM32L152xDX) || defined(STM32L152xE) || \ + defined(STM32L162xD) || defined(STM32L162xDX) || \ + defined(STM32L162xE) +#define PLATFORM_NAME "STM32L1xx Ultra Low Power High Density" + +#else +#error "STM32L1xx device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32L1XX) || defined(__DOXYGEN__) +#define STM32L1XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 16000000 /**< High speed internal clock. */ +#define STM32_LSICLK 38000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_VOS_MASK (3 << 11) /**< Core voltage mask. */ +#define STM32_VOS_1P8 (1 << 11) /**< Core voltage 1.8 Volts. */ +#define STM32_VOS_1P5 (2 << 11) /**< Core voltage 1.5 Volts. */ +#define STM32_VOS_1P2 (3 << 11) /**< Core voltage 1.2 Volts. */ + +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CR register bits definitions + * @{ + */ +#define STM32_RTCPRE_MASK (3 << 29) /**< RTCPRE mask. */ +#define STM32_RTCPRE_DIV2 (0 << 29) /**< HSE divided by 2. */ +#define STM32_RTCPRE_DIV4 (1 << 29) /**< HSE divided by 4. */ +#define STM32_RTCPRE_DIV8 (2 << 29) /**< HSE divided by 2. */ +#define STM32_RTCPRE_DIV16 (3 << 29) /**< HSE divided by 16. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ +#define STM32_SW_HSI (1 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (2 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_MSI (3 << 24) /**< MSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ + +#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ +#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ +#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ +#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ +#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ +/** @} */ + +/** + * @name RCC_ICSCR register bits definitions + * @{ + */ +#define STM32_MSIRANGE_MASK (7 << 13) /**< MSIRANGE field mask. */ +#define STM32_MSIRANGE_64K (0 << 13) /**< 64kHz nominal. */ +#define STM32_MSIRANGE_128K (1 << 13) /**< 128kHz nominal. */ +#define STM32_MSIRANGE_256K (2 << 13) /**< 256kHz nominal. */ +#define STM32_MSIRANGE_512K (3 << 13) /**< 512kHz nominal. */ +#define STM32_MSIRANGE_1M (4 << 13) /**< 1MHz nominal. */ +#define STM32_MSIRANGE_2M (5 << 13) /**< 2MHz nominal. */ +#define STM32_MSIRANGE_4M (6 << 13) /**< 4MHz nominal */ +/** @} */ + +/** + * @name RCC_CSR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 16) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 16) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1 << 16) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2 << 16) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3 << 16) /**< RTC source is HSE divided. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_1P8 +#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. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#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 +#endif + +/** + * @brief MSI frequency setting. + */ +#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) +#define STM32_MSIRANGE STM32_MSIRANGE_2M +#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. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSI +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed values are 3, 4, 6, 8, 12, 16, 32, 48. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 6 +#endif + +/** + * @brief PLL divider value. + * @note The allowed values are 2, 3, 4. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_PLLDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLDIV_VALUE 3 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 32MHz system clock from + * the internal 16MHz HSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief RTC/LCD clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief HSE divider toward RTC setting. + */ +#if !defined(STM32_RTCPRE) || defined(__DOXYGEN__) +#define STM32_RTCPRE STM32_RTCPRE_DIV2 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32L1xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L1xx_MCUCONF not defined" +#endif + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_1P8) || defined(__DOXYGEN__) +/** + * @brief Maximum HSE clock frequency at current voltage setting. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @brief Maximum SYSCLK clock frequency at current voltage setting. + */ +#define STM32_SYSCLK_MAX 32000000 + +/** + * @brief Maximum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MAX 96000000 + +/** + * @brief Minimum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MIN 6000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 32000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 32000000 + +/** + * @brief Maximum frequency not requiring a wait state for flash accesses. + */ +#define STM32_0WS_THRESHOLD 16000000 + +/** + * @brief HSI availability at current voltage settings. + */ +#define STM32_HSI_AVAILABLE TRUE + +#elif STM32_VOS == STM32_VOS_1P5 +#define STM32_HSECLK_MAX 16000000 +#define STM32_SYSCLK_MAX 16000000 +#define STM32_PLLVCO_MAX 48000000 +#define STM32_PLLVCO_MIN 6000000 +#define STM32_PCLK1_MAX 16000000 +#define STM32_PCLK2_MAX 16000000 +#define STM32_0WS_THRESHOLD 8000000 +#define STM32_HSI_AVAILABLE TRUE +#elif STM32_VOS == STM32_VOS_1P2 +#define STM32_HSECLK_MAX 4000000 +#define STM32_SYSCLK_MAX 4000000 +#define STM32_PLLVCO_MAX 24000000 +#define STM32_PLLVCO_MIN 6000000 +#define STM32_PCLK1_MAX 4000000 +#define STM32_PCLK2_MAX 4000000 +#define STM32_0WS_THRESHOLD 2000000 +#define STM32_HSI_AVAILABLE FALSE +#else +#error "invalid STM32_VOS value specified" +#endif + +/* HSI related checks.*/ +#if STM32_HSI_ENABLED +#if !STM32_HSI_AVAILABLE + #error "impossible to activate HSI under the current voltage settings" +#endif +#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_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "required HSI clock is not enabled" +#endif +#endif /* !STM32_HSI_ENABLED */ + +/* 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)" +#endif +#else /* !STM32_HSE_ENABLED */ +#if (STM32_SW == STM32_SW_HSE) || \ + ((STM32_SW == STM32_SW_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ + (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ + (STM32_RTCSEL == STM32_RTCSEL_HSEDIV) +#error "required HSE clock is not enabled" +#endif +#endif /* !STM32_HSE_ENABLED */ + +/* LSI related checks.*/ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_LSI +#error "LSI not enabled, required by STM32_MCOSEL" +#endif + +#if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* LSE related checks.*/ +#if STM32_LSE_ENABLED +#if (STM32_LSECLK == 0) +#error "impossible to activate LSE" +#endif +#if (STM32_LSECLK < 1000) || (STM32_LSECLK > 1000000) +#error "STM32_LSECLK outside acceptable range (1...1000kHz)" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) +#error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_LSE +#error "LSE not enabled, required by STM32_MCOSEL" +#endif + +#if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) +#error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL related checks.*/ +#if STM32_USB_CLOCK_ENABLED || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief PLLMUL field. + */ +#if (STM32_PLLMUL_VALUE == 3) || defined(__DOXYGEN__) +#define STM32_PLLMUL (0 << 18) +#elif STM32_PLLMUL_VALUE == 4 +#define STM32_PLLMUL (1 << 18) +#elif STM32_PLLMUL_VALUE == 6 +#define STM32_PLLMUL (2 << 18) +#elif STM32_PLLMUL_VALUE == 8 +#define STM32_PLLMUL (3 << 18) +#elif STM32_PLLMUL_VALUE == 12 +#define STM32_PLLMUL (4 << 18) +#elif STM32_PLLMUL_VALUE == 16 +#define STM32_PLLMUL (5 << 18) +#elif STM32_PLLMUL_VALUE == 24 +#define STM32_PLLMUL (6 << 18) +#elif STM32_PLLMUL_VALUE == 32 +#define STM32_PLLMUL (7 << 18) +#elif STM32_PLLMUL_VALUE == 48 +#define STM32_PLLMUL (8 << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLLDIV field. + */ +#if (STM32_PLLDIV_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLDIV (1 << 22) +#elif STM32_PLLDIV_VALUE == 3 +#define STM32_PLLDIV (2 << 22) +#elif STM32_PLLDIV_VALUE == 4 +#define STM32_PLLDIV (3 << 22) +#else +#error "invalid STM32_PLLDIV_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 < 2000000) || (STM32_PLLCLKIN > 24000000) +#error "STM32_PLLCLKIN outside acceptable range (2...24MHz)" +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLDIV_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < 2000000) || (STM32_PLLCLKOUT > 32000000) +#error "STM32_PLLCLKOUT outside acceptable range (2...32MHz)" +#endif + +/** + * @brief MSI frequency. + */ +#if STM32_MSIRANGE == STM32_MSIRANGE_64K +#define STM32_MSICLK 65500 +#elif STM32_MSIRANGE == STM32_MSIRANGE_128K +#define STM32_MSICLK 131000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_256K +#define STM32_MSICLK 262000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_512K +#define STM32_MSICLK 524000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_1M +#define STM32_MSICLK 1050000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_2M +#define STM32_MSICLK 2100000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_4M +#define STM32_MSICLK 4200000 +#else +#error "invalid STM32_MSIRANGE value specified" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK 2100000 +#elif (STM32_SW == STM32_SW_MSI) +#define STM32_SYSCLK STM32_MSICLK +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief MCO clock before divider. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 +#elif STM32_MCOSEL == STM32_MCOSEL_HSI +#define STM32_MCODIVCLK STM32_HSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_MSI +#define STM32_MCODIVCLK STM32_MSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK +#elif STM32_MCOSEL == STM32_MCOSEL_PLL +#define STM32_MCODIVCLK STM32_PLLCLKOUT +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief HSE divider toward RTC clock. + */ +#if (STM32_RTCPRE == STM32_RTCPRE_DIV2) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 2) +#elif (STM32_RTCPRE == STM32_RTCPRE_DIV4) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 4) +#elif (STM32_RTCPRE == STM32_RTCPRE_DIV8) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 8) +#elif (STM32_RTCPRE == STM32_RTCPRE_DIV16) || defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / 16) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief RTC/LCD clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK STM32_HSEDIVCLK +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USB frequency. + */ +#define STM32_USBCLK (STM32_PLLVCO / 2) + +/** + * @brief Timers 2, 3, 4, 6, 7 clock. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 9, 10, 11 clock. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS1 0x00000000 +#else +#define STM32_FLASHBITS1 0x00000004 +#define STM32_FLASHBITS2 0x00000007 +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/platform.dox b/os/hal/ports/STM32/STM32L1xx/platform.dox index 801ed83a36..09dc6742e5 100644 --- a/os/hal/ports/STM32/STM32L1xx/platform.dox +++ b/os/hal/ports/STM32/STM32L1xx/platform.dox @@ -1,315 +1,315 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @defgroup STM32L1xx_DRIVERS STM32L1xx Drivers - * @details This section describes all the supported drivers on the STM32L1xx - * platform and the implementation details of the single drivers. - * - * @ingroup platforms - */ - -/** - * @defgroup STM32L1xx_HAL STM32L1xx Initialization Support - * @details The STM32L1xx HAL support is responsible for system initialization. - * - * @section stm32l1xx_hal_1 Supported HW resources - * - PLL1. - * - RCC. - * - Flash. - * . - * @section stm32l1xx_hal_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_ADC STM32L1xx ADC Support - * @details The STM32L1xx ADC driver supports the ADC peripherals using DMA - * channels for maximum performance. - * - * @section stm32l1xx_adc_1 Supported HW resources - * - ADC1. - * - DMA1. - * . - * @section stm32l1xx_adc_2 STM32L1xx ADC driver implementation features - * - Clock stop for reduced power usage when the driver is in stop state. - * - Streaming conversion using DMA for maximum performance. - * - Programmable ADC interrupt priority level. - * - Programmable DMA bus priority for each DMA channel. - * - Programmable DMA interrupt priority for each DMA channel. - * - DMA and ADC errors detection. - * . - * @ingroup STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_EXT STM32L1xx EXT Support - * @details The STM32L1xx EXT driver uses the EXTI peripheral. - * - * @section stm32l1xx_ext_1 Supported HW resources - * - EXTI. - * . - * @section stm32l1xx_ext_2 STM32L1xx EXT driver implementation features - * - Each EXTI channel can be independently enabled and programmed. - * - Programmable EXTI interrupts priority level. - * - Capability to work as event sources (WFE) rather than interrupt sources. - * . - * @ingroup STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_GPT STM32L1xx GPT Support - * @details The STM32L1xx GPT driver uses the TIMx peripherals. - * - * @section stm32l1xx_gpt_1 Supported HW resources - * - TIM2. - * - TIM3. - * - TIM4. - * . - * @section stm32l1xx_gpt_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_ICU STM32L1xx ICU Support - * @details The STM32L1xx ICU driver uses the TIMx peripherals. - * - * @section stm32l1xx_icu_1 Supported HW resources - * - TIM2. - * - TIM3. - * - TIM4. - * . - * @section stm32l1xx_icu_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_PAL STM32L1xx PAL Support - * @details The STM32L1xx PAL driver uses the GPIO peripherals. - * - * @section stm32l1xx_pal_1 Supported HW resources - * - GPIOA. - * - GPIOB. - * - GPIOC. - * - GPIOD. - * - GPIOE. - * - GPIOH. - * . - * @section stm32l1xx_pal_2 STM32L1xx 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 stm32l1xx_pal_3 Supported PAL setup modes - * The STM32L1xx 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 stm32l1xx_pal_4 Suboptimal behavior - * The STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_PWM STM32L1xx PWM Support - * @details The STM32L1xx PWM driver uses the TIMx peripherals. - * - * @section stm32l1xx_pwm_1 Supported HW resources - * - TIM1. - * - TIM2. - * - TIM3. - * - TIM4. - * . - * @section stm32l1xx_pwm_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_SERIAL STM32L1xx Serial Support - * @details The STM32L1xx Serial driver uses the USART/UART peripherals in a - * buffered, interrupt driven, implementation. - * - * @section stm32l1xx_serial_1 Supported HW resources - * The serial driver can support any of the following hardware resources: - * - USART1. - * - USART2. - * - USART3 (where present). - * - UART4 (where present). - * - UART5 (where present). - * . - * @section stm32l1xx_serial_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_SPI STM32L1xx SPI Support - * @details The SPI driver supports the STM32L1xx SPI peripherals using DMA - * channels for maximum performance. - * - * @section stm32l1xx_spi_1 Supported HW resources - * - SPI1. - * - SPI2. - * - SPI3 (where present). - * - DMA1. - * - DMA2 (where present). - * . - * @section stm32l1xx_spi_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_UART STM32L1xx UART Support - * @details The UART driver supports the STM32L1xx USART peripherals using DMA - * channels for maximum performance. - * - * @section stm32l1xx_uart_1 Supported HW resources - * The UART driver can support any of the following hardware resources: - * - USART1. - * - USART2. - * - USART3 (where present). - * - DMA1. - * . - * @section stm32l1xx_uart_2 STM32L1xx 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 STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_USB STM32L1xx USB Support - * @details The USB driver supports the STM32L1xx USB peripheral. - * - * @section stm32l1xx_usb_1 Supported HW resources - * The USB driver can support any of the following hardware resources: - * - USB. - * . - * @section stm32l1xx_usb_2 STM32L1xx USB driver implementation features - * - Clock stop for reduced power usage when the driver is in stop state. - * - Programmable interrupt priority levels. - * - Each endpoint programmable in Control, Bulk and Interrupt modes. - * . - * @ingroup STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_PLATFORM_DRIVERS STM32L1xx Platform Drivers - * @details Platform support drivers. Platform drivers do not implement HAL - * standard driver templates, their role is to support platform - * specific functionalities. - * - * @ingroup STM32L1xx_DRIVERS - */ - -/** - * @defgroup STM32L1xx_DMA STM32L1xx DMA Support - * @details This DMA helper driver is used by the other drivers in order to - * access the shared DMA resources in a consistent way. - * - * @section stm32l1xx_dma_1 Supported HW resources - * The DMA driver can support any of the following hardware resources: - * - DMA1. - * . - * @section stm32l1xx_dma_2 STM32L1xx DMA driver implementation features - * - Exports helper functions/macros to the other drivers that share the - * DMA resource. - * - Automatic DMA clock stop when not in use by any driver. - * - DMA streams and interrupt vectors sharing among multiple drivers. - * . - * @ingroup STM32L1xx_PLATFORM_DRIVERS - */ - -/** - * @defgroup STM32L1xx_ISR STM32L1xx ISR Support - * @details This ISR helper driver is used by the other drivers in order to - * map ISR names to physical vector names. - * - * @ingroup STM32L1xx_PLATFORM_DRIVERS - */ - -/** - * @defgroup STM32L1xx_RCC STM32L1xx RCC Support - * @details This RCC helper driver is used by the other drivers in order to - * access the shared RCC resources in a consistent way. - * - * @section stm32f1xx_rcc_1 Supported HW resources - * - RCC. - * . - * @section stm32l1xx_rcc_2 STM32L1xx RCC driver implementation features - * - Peripherals reset. - * - Peripherals clock enable. - * - Peripherals clock disable. - * . - * @ingroup STM32L1xx_PLATFORM_DRIVERS - */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @defgroup STM32L1xx_DRIVERS STM32L1xx Drivers + * @details This section describes all the supported drivers on the STM32L1xx + * platform and the implementation details of the single drivers. + * + * @ingroup platforms + */ + +/** + * @defgroup STM32L1xx_HAL STM32L1xx Initialization Support + * @details The STM32L1xx HAL support is responsible for system initialization. + * + * @section stm32l1xx_hal_1 Supported HW resources + * - PLL1. + * - RCC. + * - Flash. + * . + * @section stm32l1xx_hal_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_ADC STM32L1xx ADC Support + * @details The STM32L1xx ADC driver supports the ADC peripherals using DMA + * channels for maximum performance. + * + * @section stm32l1xx_adc_1 Supported HW resources + * - ADC1. + * - DMA1. + * . + * @section stm32l1xx_adc_2 STM32L1xx ADC driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Streaming conversion using DMA for maximum performance. + * - Programmable ADC interrupt priority level. + * - Programmable DMA bus priority for each DMA channel. + * - Programmable DMA interrupt priority for each DMA channel. + * - DMA and ADC errors detection. + * . + * @ingroup STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_EXT STM32L1xx EXT Support + * @details The STM32L1xx EXT driver uses the EXTI peripheral. + * + * @section stm32l1xx_ext_1 Supported HW resources + * - EXTI. + * . + * @section stm32l1xx_ext_2 STM32L1xx EXT driver implementation features + * - Each EXTI channel can be independently enabled and programmed. + * - Programmable EXTI interrupts priority level. + * - Capability to work as event sources (WFE) rather than interrupt sources. + * . + * @ingroup STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_GPT STM32L1xx GPT Support + * @details The STM32L1xx GPT driver uses the TIMx peripherals. + * + * @section stm32l1xx_gpt_1 Supported HW resources + * - TIM2. + * - TIM3. + * - TIM4. + * . + * @section stm32l1xx_gpt_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_ICU STM32L1xx ICU Support + * @details The STM32L1xx ICU driver uses the TIMx peripherals. + * + * @section stm32l1xx_icu_1 Supported HW resources + * - TIM2. + * - TIM3. + * - TIM4. + * . + * @section stm32l1xx_icu_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_PAL STM32L1xx PAL Support + * @details The STM32L1xx PAL driver uses the GPIO peripherals. + * + * @section stm32l1xx_pal_1 Supported HW resources + * - GPIOA. + * - GPIOB. + * - GPIOC. + * - GPIOD. + * - GPIOE. + * - GPIOH. + * . + * @section stm32l1xx_pal_2 STM32L1xx 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 stm32l1xx_pal_3 Supported PAL setup modes + * The STM32L1xx 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 stm32l1xx_pal_4 Suboptimal behavior + * The STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_PWM STM32L1xx PWM Support + * @details The STM32L1xx PWM driver uses the TIMx peripherals. + * + * @section stm32l1xx_pwm_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * . + * @section stm32l1xx_pwm_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_SERIAL STM32L1xx Serial Support + * @details The STM32L1xx Serial driver uses the USART/UART peripherals in a + * buffered, interrupt driven, implementation. + * + * @section stm32l1xx_serial_1 Supported HW resources + * The serial driver can support any of the following hardware resources: + * - USART1. + * - USART2. + * - USART3 (where present). + * - UART4 (where present). + * - UART5 (where present). + * . + * @section stm32l1xx_serial_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_SPI STM32L1xx SPI Support + * @details The SPI driver supports the STM32L1xx SPI peripherals using DMA + * channels for maximum performance. + * + * @section stm32l1xx_spi_1 Supported HW resources + * - SPI1. + * - SPI2. + * - SPI3 (where present). + * - DMA1. + * - DMA2 (where present). + * . + * @section stm32l1xx_spi_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_UART STM32L1xx UART Support + * @details The UART driver supports the STM32L1xx USART peripherals using DMA + * channels for maximum performance. + * + * @section stm32l1xx_uart_1 Supported HW resources + * The UART driver can support any of the following hardware resources: + * - USART1. + * - USART2. + * - USART3 (where present). + * - DMA1. + * . + * @section stm32l1xx_uart_2 STM32L1xx 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 STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_USB STM32L1xx USB Support + * @details The USB driver supports the STM32L1xx USB peripheral. + * + * @section stm32l1xx_usb_1 Supported HW resources + * The USB driver can support any of the following hardware resources: + * - USB. + * . + * @section stm32l1xx_usb_2 STM32L1xx USB driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Programmable interrupt priority levels. + * - Each endpoint programmable in Control, Bulk and Interrupt modes. + * . + * @ingroup STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_PLATFORM_DRIVERS STM32L1xx Platform Drivers + * @details Platform support drivers. Platform drivers do not implement HAL + * standard driver templates, their role is to support platform + * specific functionalities. + * + * @ingroup STM32L1xx_DRIVERS + */ + +/** + * @defgroup STM32L1xx_DMA STM32L1xx DMA Support + * @details This DMA helper driver is used by the other drivers in order to + * access the shared DMA resources in a consistent way. + * + * @section stm32l1xx_dma_1 Supported HW resources + * The DMA driver can support any of the following hardware resources: + * - DMA1. + * . + * @section stm32l1xx_dma_2 STM32L1xx DMA driver implementation features + * - Exports helper functions/macros to the other drivers that share the + * DMA resource. + * - Automatic DMA clock stop when not in use by any driver. + * - DMA streams and interrupt vectors sharing among multiple drivers. + * . + * @ingroup STM32L1xx_PLATFORM_DRIVERS + */ + +/** + * @defgroup STM32L1xx_ISR STM32L1xx ISR Support + * @details This ISR helper driver is used by the other drivers in order to + * map ISR names to physical vector names. + * + * @ingroup STM32L1xx_PLATFORM_DRIVERS + */ + +/** + * @defgroup STM32L1xx_RCC STM32L1xx RCC Support + * @details This RCC helper driver is used by the other drivers in order to + * access the shared RCC resources in a consistent way. + * + * @section stm32f1xx_rcc_1 Supported HW resources + * - RCC. + * . + * @section stm32l1xx_rcc_2 STM32L1xx RCC driver implementation features + * - Peripherals reset. + * - Peripherals clock enable. + * - Peripherals clock disable. + * . + * @ingroup STM32L1xx_PLATFORM_DRIVERS + */ diff --git a/os/hal/ports/STM32/STM32L1xx/platform.mk b/os/hal/ports/STM32/STM32L1xx/platform.mk index 43e7d1b0a2..7510bac105 100644 --- a/os/hal/ports/STM32/STM32L1xx/platform.mk +++ b/os/hal/ports/STM32/STM32L1xx/platform.mk @@ -1,46 +1,46 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c -endif -else -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/STM32L1xx/hal_adc_lld.c +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32L1xx/stm32_isr.c b/os/hal/ports/STM32/STM32L1xx/stm32_isr.c index d6353c3471..0f2f7c8c87 100644 --- a/os/hal/ports/STM32/STM32L1xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32L1xx/stm32_isr.c @@ -1,255 +1,255 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/stm32_isr.c - * @brief STM32L1xx ISR handler code. - * - * @addtogroup STM32L1xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) -#if !defined(STM32_DISABLE_EXTI0_HANDLER) -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 0); - EXTI->PR = pr; - - exti_serve_irq(pr, 0); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI1_HANDLER) -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 1); - EXTI->PR = pr; - - exti_serve_irq(pr, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_HANDLER) -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 2); - EXTI->PR = pr; - - exti_serve_irq(pr, 2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI3_HANDLER) -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 3); - EXTI->PR = pr; - - exti_serve_irq(pr, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_HANDLER) -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & (1U << 4); - EXTI->PR = pr; - - exti_serve_irq(pr, 4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | - (1U << 9)); - EXTI->PR = pr; - - exti_serve_irq(pr, 5); - exti_serve_irq(pr, 6); - exti_serve_irq(pr, 7); - exti_serve_irq(pr, 8); - exti_serve_irq(pr, 9); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR; - pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | - (1U << 14) | (1U << 15)); - EXTI->PR = pr; - - exti_serve_irq(pr, 10); - exti_serve_irq(pr, 11); - exti_serve_irq(pr, 12); - exti_serve_irq(pr, 13); - exti_serve_irq(pr, 14); - exti_serve_irq(pr, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - -#if HAL_USE_PAL - nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); - nvicEnableVector(EXTI2_IRQn, STM32_IRQ_EXTI2_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); -#endif -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - -#if HAL_USE_PAL - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); -#endif -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/stm32_isr.c + * @brief STM32L1xx ISR handler code. + * + * @addtogroup STM32L1xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__) +#if !defined(STM32_DISABLE_EXTI0_HANDLER) +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 0); + EXTI->PR = pr; + + exti_serve_irq(pr, 0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI1_HANDLER) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 1); + EXTI->PR = pr; + + exti_serve_irq(pr, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_HANDLER) +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 2); + EXTI->PR = pr; + + exti_serve_irq(pr, 2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI3_HANDLER) +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 3); + EXTI->PR = pr; + + exti_serve_irq(pr, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_HANDLER) +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & (1U << 4); + EXTI->PR = pr; + + exti_serve_irq(pr, 4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) | + (1U << 9)); + EXTI->PR = pr; + + exti_serve_irq(pr, 5); + exti_serve_irq(pr, 6); + exti_serve_irq(pr, 7); + exti_serve_irq(pr, 8); + exti_serve_irq(pr, 9); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR; + pr &= EXTI->IMR & ((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | + (1U << 14) | (1U << 15)); + EXTI->PR = pr; + + exti_serve_irq(pr, 10); + exti_serve_irq(pr, 11); + exti_serve_irq(pr, 12); + exti_serve_irq(pr, 13); + exti_serve_irq(pr, 14); + exti_serve_irq(pr, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#endif /* HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS) */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + +#if HAL_USE_PAL + nvicEnableVector(EXTI0_IRQn, STM32_IRQ_EXTI0_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_IRQ_EXTI1_PRIORITY); + nvicEnableVector(EXTI2_IRQn, STM32_IRQ_EXTI2_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_IRQ_EXTI3_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_IRQ_EXTI4_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_IRQ_EXTI5_9_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_IRQ_EXTI10_15_PRIORITY); +#endif +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +#if HAL_USE_PAL + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); +#endif +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/stm32_isr.h b/os/hal/ports/STM32/STM32L1xx/stm32_isr.h index c29cd144f0..6919a12174 100644 --- a/os/hal/ports/STM32/STM32L1xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32L1xx/stm32_isr.h @@ -1,230 +1,230 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/stm32_isr.h - * @brief STM32L1xx ISR handler header. - * - * @addtogroup STM32L1xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 - -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 - -/* - * TIM units. - */ -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER VectorF8 -#define STM32_TIM6_HANDLER VectorEC -#define STM32_TIM7_HANDLER VectorF0 -#define STM32_TIM9_HANDLER VectorA4 -#define STM32_TIM10_HANDLER VectorA8 -#define STM32_TIM11_HANDLER VectorAC - -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 46 -#define STM32_TIM6_NUMBER 43 -#define STM32_TIM7_NUMBER 44 -#define STM32_TIM9_NUMBER 25 -#define STM32_TIM10_NUMBER 26 -#define STM32_TIM11_NUMBER 27 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector100 -#define STM32_UART5_HANDLER Vector104 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 48 -#define STM32_UART5_NUMBER 49 -/* - * USB units. - */ -#define STM32_USB1_HP_HANDLER Vector8C -#define STM32_USB1_LP_HANDLER Vector90 - -#define STM32_USB1_HP_NUMBER 19 -#define STM32_USB1_LP_NUMBER 20 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI0_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI1_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI2_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI3_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI4_PRIORITY 6 -#endif - -/** - * @brief EXTI9..5 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#endif - -/** - * @brief EXTI15..10 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI16_PRIORITY 6 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI17_PRIORITY 6 -#endif - -/** - * @brief EXTI18 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI18_PRIORITY 6 -#endif - -/** - * @brief EXTI19 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI19_PRIORITY 6 -#endif - -/** - * @brief EXTI20 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI20_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI20_PRIORITY 6 -#endif - -/** - * @brief EXTI21..22 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI21_22_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI21_22_PRIORITY 6 -#endif - -/** - * @brief EXTI23 interrupt priority level setting. - */ -#if !defined(STM32_IRQ_EXTI23_PRIORITY) || defined(__DOXYGEN__) -#define STM32_IRQ_EXTI23_PRIORITY 6 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/stm32_isr.h + * @brief STM32L1xx ISR handler header. + * + * @addtogroup STM32L1xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 + +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 + +/* + * TIM units. + */ +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER VectorF8 +#define STM32_TIM6_HANDLER VectorEC +#define STM32_TIM7_HANDLER VectorF0 +#define STM32_TIM9_HANDLER VectorA4 +#define STM32_TIM10_HANDLER VectorA8 +#define STM32_TIM11_HANDLER VectorAC + +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 46 +#define STM32_TIM6_NUMBER 43 +#define STM32_TIM7_NUMBER 44 +#define STM32_TIM9_NUMBER 25 +#define STM32_TIM10_NUMBER 26 +#define STM32_TIM11_NUMBER 27 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector100 +#define STM32_UART5_HANDLER Vector104 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 48 +#define STM32_UART5_NUMBER 49 +/* + * USB units. + */ +#define STM32_USB1_HP_HANDLER Vector8C +#define STM32_USB1_LP_HANDLER Vector90 + +#define STM32_USB1_HP_NUMBER 19 +#define STM32_USB1_LP_NUMBER 20 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI0_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI0_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI1_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI2_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI3_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI4_PRIORITY 6 +#endif + +/** + * @brief EXTI9..5 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI5_9_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#endif + +/** + * @brief EXTI15..10 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI10_15_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI16_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI16_PRIORITY 6 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI17_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI17_PRIORITY 6 +#endif + +/** + * @brief EXTI18 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI18_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI18_PRIORITY 6 +#endif + +/** + * @brief EXTI19 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI19_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI19_PRIORITY 6 +#endif + +/** + * @brief EXTI20 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI20_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI20_PRIORITY 6 +#endif + +/** + * @brief EXTI21..22 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI21_22_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI21_22_PRIORITY 6 +#endif + +/** + * @brief EXTI23 interrupt priority level setting. + */ +#if !defined(STM32_IRQ_EXTI23_PRIORITY) || defined(__DOXYGEN__) +#define STM32_IRQ_EXTI23_PRIORITY 6 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/stm32_rcc.h b/os/hal/ports/STM32/STM32L1xx/stm32_rcc.h index 11cbe332c2..5c0d318d22 100644 --- a/os/hal/ports/STM32/STM32L1xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32L1xx/stm32_rcc.h @@ -1,795 +1,795 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32l1xx.h. - * - * @addtogroup STM32L1xx_RCC - * @{ - */ - -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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); \ - else \ - RCC->APB1LPENR &= ~(mask); \ - (void)RCC->APB1LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccDisableAPB1(mask) { \ - RCC->APB1ENR &= ~(mask); \ - RCC->APB1LPENR &= ~(mask); \ - (void)RCC->APB1LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB1RSTR; \ -} - -/** - * @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); \ - else \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2LPENR &= ~(mask); \ - (void)RCC->APB2LPENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ - if (lp) \ - RCC->AHBLPENR |= (mask); \ - else \ - RCC->AHBLPENR &= ~(mask); \ - (void)RCC->AHBLPENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccDisableAHB(mask) { \ - RCC->AHBENR &= ~(mask); \ - RCC->AHBLPENR &= ~(mask); \ - (void)RCC->AHBLPENR; \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR &= ~(mask); \ - (void)RCC->AHBRSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @api - */ -#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) - -/** - * @brief Enables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) - -/** - * @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. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM9 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) - -/** - * @brief Disables the TIM9 peripheral clock. - * - * @api - */ -#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) - -/** - * @brief Resets the TIM9 peripheral. - * - * @api - */ -#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) - -/** - * @brief Enables the TIM10 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) - -/** - * @brief Disables the TIM10 peripheral clock. - * - * @api - */ -#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) - -/** - * @brief Resets the TIM10 peripheral. - * - * @api - */ -#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) - -/** - * @brief Enables the TIM10 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) - -/** - * @brief Disables the TIM11 peripheral clock. - * - * @api - */ -#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) - -/** - * @brief Resets the TIM11 peripheral. - * - * @api - */ -#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) - -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) - -/** - * @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. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32l1xx.h. + * + * @addtogroup STM32L1xx_RCC + * @{ + */ + +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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); \ + else \ + RCC->APB1LPENR &= ~(mask); \ + (void)RCC->APB1LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccDisableAPB1(mask) { \ + RCC->APB1ENR &= ~(mask); \ + RCC->APB1LPENR &= ~(mask); \ + (void)RCC->APB1LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB1RSTR; \ +} + +/** + * @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); \ + else \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2LPENR &= ~(mask); \ + (void)RCC->APB2LPENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ + if (lp) \ + RCC->AHBLPENR |= (mask); \ + else \ + RCC->AHBLPENR &= ~(mask); \ + (void)RCC->AHBLPENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccDisableAHB(mask) { \ + RCC->AHBENR &= ~(mask); \ + RCC->AHBLPENR &= ~(mask); \ + (void)RCC->AHBLPENR; \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR &= ~(mask); \ + (void)RCC->AHBRSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @api + */ +#define rccDisableADC1() rccDisableAPB2(RCC_APB2ENR_ADC1EN) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1(RCC_APB1ENR_DACEN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DACRST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB(RCC_AHBENR_DMA1EN) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) + +/** + * @brief Enables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB(RCC_AHBENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1(RCC_APB1ENR_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1(RCC_APB1ENR_I2C1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1(RCC_APB1ENR_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1(RCC_APB1ENR_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1(RCC_APB1ENR_TIM2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1(RCC_APB1ENR_TIM3EN) + +/** + * @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. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1(RCC_APB1ENR_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1(RCC_APB1ENR_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1(RCC_APB1ENR_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1(RCC_APB1ENR_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM9 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) + +/** + * @brief Disables the TIM9 peripheral clock. + * + * @api + */ +#define rccDisableTIM9() rccDisableAPB2(RCC_APB2ENR_TIM9EN) + +/** + * @brief Resets the TIM9 peripheral. + * + * @api + */ +#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) + +/** + * @brief Enables the TIM10 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM10(lp) rccEnableAPB2(RCC_APB2ENR_TIM10EN, lp) + +/** + * @brief Disables the TIM10 peripheral clock. + * + * @api + */ +#define rccDisableTIM10() rccDisableAPB2(RCC_APB2ENR_TIM10EN) + +/** + * @brief Resets the TIM10 peripheral. + * + * @api + */ +#define rccResetTIM10() rccResetAPB2(RCC_APB2RSTR_TIM10RST) + +/** + * @brief Enables the TIM10 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) + +/** + * @brief Disables the TIM11 peripheral clock. + * + * @api + */ +#define rccDisableTIM11() rccDisableAPB2(RCC_APB2ENR_TIM11EN) + +/** + * @brief Resets the TIM11 peripheral. + * + * @api + */ +#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) + +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1(RCC_APB1ENR_USART2EN) + +/** + * @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. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1(RCC_APB1ENR_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1(RCC_APB1ENR_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1(RCC_APB1ENR_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1(RCC_APB1ENR_USBEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L1xx/stm32_registry.h b/os/hal/ports/STM32/STM32L1xx/stm32_registry.h index d227aa1e34..8e0b28525d 100644 --- a/os/hal/ports/STM32/STM32L1xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L1xx/stm32_registry.h @@ -1,377 +1,377 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L1xx/stm32_registry.h - * @brief STM32L1xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -#if defined(STM32L100xB) || defined(STM32L151xB) || defined(STM32L152xB) -#define STM32L1XX_PROD_CAT 1 - -#elif defined(STM32L100xBA) || defined(STM32L151xBA) || defined(STM32L152xBA) -#define STM32L1XX_PROD_CAT 2 - -#elif defined(STM32L100xC) || defined(STM32L151xC) || \ - defined(STM32L151xCA) || defined(STM32L152xC) || \ - defined(STM32L152xCA) || defined(STM32L162xC) || \ - defined(STM32L162xCA) -#define STM32L1XX_PROD_CAT 3 - -#elif defined(STM32L151xD) || defined(STM32L152xD) || \ - defined(STM32L162xD) -#define STM32L1XX_PROD_CAT 4 - -#elif defined(STM32L151xE) || defined (STM32L152xE) || \ - defined(STM32L162xE) -#define STM32L1XX_PROD_CAT 5 - -#elif defined(STM32L151xDX) || defined (STM32L152xDX) || \ - defined(STM32L162xDX) -#define STM32L1XX_PROD_CAT 6 - -#else -#error "STM32L1xx device not specified" -#endif - -#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC) -#define STM32L1XX_VALUE_LINE TRUE -#else -#define STM32L1XX_VALUE_LINE FALSE -#endif - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32L1xx capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR FALSE - -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 - -#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ - defined(__DOXYGEN__) -#define STM32_DMA2_NUM_CHANNELS 0 -#else -#define STM32_DMA2_NUM_CHANNELS 5 -#define STM32_DMA2_CH1_HANDLER Vector108 -#define STM32_DMA2_CH2_HANDLER Vector10C -#define STM32_DMA2_CH3_HANDLER Vector110 -#define STM32_DMA2_CH4_HANDLER Vector114 -#define STM32_DMA2_CH5_HANDLER Vector118 -#define STM32_DMA2_CH1_NUMBER 50 -#define STM32_DMA2_CH2_NUMBER 51 -#define STM32_DMA2_CH3_NUMBER 52 -#define STM32_DMA2_CH4_NUMBER 53 -#define STM32_DMA2_CH5_NUMBER 54 -#endif - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ - defined(__DOXYGEN__) -#define STM32_EXTI_NUM_LINES 23 -#else -#define STM32_EXTI_NUM_LINES 24 -#endif -#define STM32_EXTI_IMR1_MASK 0x00000000U - -#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ - (STM32L1XX_PROD_CAT == 3) || defined(__DOXYGEN__) -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOHEN) -#else -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ - RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | \ - RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | \ - RCC_AHBENR_GPIOFEN | \ - RCC_AHBENR_GPIOGEN | \ - RCC_AHBENR_GPIOHEN) -#endif - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#if (STM32L1XX_PROD_CAT == 1) || defined(__DOXYGEN__) -#define STM32_RTC_HAS_SUBSECONDS FALSE -#else -#define STM32_RTC_HAS_SUBSECONDS TRUE -#endif -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#if STM32L1XX_VALUE_LINE || defined(__DOXYGEN__) -#define STM32_RTC_STORAGE_SIZE 20 -#elif (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) -#define STM32_RTC_STORAGE_SIZE 80 -#else -#define STM32_RTC_STORAGE_SIZE 128 -#endif -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 3 -#define STM32_RTC_WKUP_NUMBER 1 -#define STM32_RTC_ALARM_NUMBER 2 -#define STM32_RTC_ALARM_EXTI 17 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ -} while (false) - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S TRUE -#define STM32_SPI2_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ - defined(__DOXYGEN__) -#define STM32_HAS_SPI3 FALSE -#else -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S TRUE -#define STM32_SPI3_I2S_FULLDUPLEX FALSE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#endif - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS FALSE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ - defined(__DOXYGEN__) -#define STM32_HAS_TIM5 FALSE -#else -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 -#endif - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 2 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 2 - -#define STM32_HAS_TIM1 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ - (STM32L1XX_PROD_CAT == 3) || defined(__DOXYGEN__) -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#else -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE -#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#endif - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE -#define STM32_HAS_LPUART1 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 FALSE -#define STM32_USB_PMA_SIZE 512 -#define STM32_USB_HAS_BCDR FALSE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED FALSE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE FALSE - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L1xx/stm32_registry.h + * @brief STM32L1xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +#if defined(STM32L100xB) || defined(STM32L151xB) || defined(STM32L152xB) +#define STM32L1XX_PROD_CAT 1 + +#elif defined(STM32L100xBA) || defined(STM32L151xBA) || defined(STM32L152xBA) +#define STM32L1XX_PROD_CAT 2 + +#elif defined(STM32L100xC) || defined(STM32L151xC) || \ + defined(STM32L151xCA) || defined(STM32L152xC) || \ + defined(STM32L152xCA) || defined(STM32L162xC) || \ + defined(STM32L162xCA) +#define STM32L1XX_PROD_CAT 3 + +#elif defined(STM32L151xD) || defined(STM32L152xD) || \ + defined(STM32L162xD) +#define STM32L1XX_PROD_CAT 4 + +#elif defined(STM32L151xE) || defined (STM32L152xE) || \ + defined(STM32L162xE) +#define STM32L1XX_PROD_CAT 5 + +#elif defined(STM32L151xDX) || defined (STM32L152xDX) || \ + defined(STM32L162xDX) +#define STM32L1XX_PROD_CAT 6 + +#else +#error "STM32L1xx device not specified" +#endif + +#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC) +#define STM32L1XX_VALUE_LINE TRUE +#else +#define STM32L1XX_VALUE_LINE FALSE +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32L1xx capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR FALSE + +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 + +#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ + defined(__DOXYGEN__) +#define STM32_DMA2_NUM_CHANNELS 0 +#else +#define STM32_DMA2_NUM_CHANNELS 5 +#define STM32_DMA2_CH1_HANDLER Vector108 +#define STM32_DMA2_CH2_HANDLER Vector10C +#define STM32_DMA2_CH3_HANDLER Vector110 +#define STM32_DMA2_CH4_HANDLER Vector114 +#define STM32_DMA2_CH5_HANDLER Vector118 +#define STM32_DMA2_CH1_NUMBER 50 +#define STM32_DMA2_CH2_NUMBER 51 +#define STM32_DMA2_CH3_NUMBER 52 +#define STM32_DMA2_CH4_NUMBER 53 +#define STM32_DMA2_CH5_NUMBER 54 +#endif + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ + defined(__DOXYGEN__) +#define STM32_EXTI_NUM_LINES 23 +#else +#define STM32_EXTI_NUM_LINES 24 +#endif +#define STM32_EXTI_IMR1_MASK 0x00000000U + +#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ + (STM32L1XX_PROD_CAT == 3) || defined(__DOXYGEN__) +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOHEN) +#else +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHBENR_GPIOAEN | \ + RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | \ + RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | \ + RCC_AHBENR_GPIOFEN | \ + RCC_AHBENR_GPIOGEN | \ + RCC_AHBENR_GPIOHEN) +#endif + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#if (STM32L1XX_PROD_CAT == 1) || defined(__DOXYGEN__) +#define STM32_RTC_HAS_SUBSECONDS FALSE +#else +#define STM32_RTC_HAS_SUBSECONDS TRUE +#endif +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#if STM32L1XX_VALUE_LINE || defined(__DOXYGEN__) +#define STM32_RTC_STORAGE_SIZE 20 +#elif (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) +#define STM32_RTC_STORAGE_SIZE 80 +#else +#define STM32_RTC_STORAGE_SIZE 128 +#endif +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 3 +#define STM32_RTC_WKUP_NUMBER 1 +#define STM32_RTC_ALARM_NUMBER 2 +#define STM32_RTC_ALARM_EXTI 17 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ +} while (false) + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S TRUE +#define STM32_SPI2_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ + defined(__DOXYGEN__) +#define STM32_HAS_SPI3 FALSE +#else +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S TRUE +#define STM32_SPI3_I2S_FULLDUPLEX FALSE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#endif + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS FALSE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ + defined(__DOXYGEN__) +#define STM32_HAS_TIM5 FALSE +#else +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 +#endif + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 2 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 2 + +#define STM32_HAS_TIM1 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \ + (STM32L1XX_PROD_CAT == 3) || defined(__DOXYGEN__) +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#else +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#endif + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE +#define STM32_HAS_LPUART1 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 FALSE +#define STM32_USB_PMA_SIZE 512 +#define STM32_USB_HAS_BCDR FALSE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED FALSE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE FALSE + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/hal_lld.c b/os/hal/ports/STM32/STM32L4xx+/hal_lld.c index 6a6d6de997..f29d5e6705 100644 --- a/os/hal/ports/STM32/STM32L4xx+/hal_lld.c +++ b/os/hal/ports/STM32/STM32L4xx+/hal_lld.c @@ -1,381 +1,381 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/hal_lld.c - * @brief STM32L4xx+ HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32l4xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing RTC clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if STM32_MSIPLL_ENABLED - /* MSI PLL activation depends on LSE. Reactivating and checking for - MSI stability.*/ - RCC->CR |= RCC_CR_MSIPLLEN; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; /* Wait until MSI is stable. */ -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - - /* Low speed output mode.*/ - RCC->BDCR |= STM32_LSCOSEL; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB1(~0); - rccResetAHB2(~STM32_GPIO_EN_MASK); - rccResetAHB3(~0); - rccResetAPB1R1(~RCC_APB1RSTR1_PWRRST); - rccResetAPB1R2(~0); - rccResetAPB2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK); -#else - PWR->CR2 = 0; -#endif /* STM32_PVD_ENABLE */ - - /* Enabling independent VDDUSB.*/ -#if HAL_USE_USB - PWR->CR2 |= PWR_CR2_USV; -#endif /* HAL_USE_USB */ - - /* Enabling independent VDDIO2 required by GPIOG.*/ -#if STM32_HAS_GPIOG - PWR->CR2 |= PWR_CR2_IOSV; -#endif /* STM32_HAS_GPIOG */ -} - -/** - * @brief STM32L4xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ -#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR1_RTCAPBEN) - RCC->APB1ENR1 = RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN; -#else - RCC->APB1ENR1 = RCC_APB1ENR1_PWREN; -#endif - - /* Initial clocks setup and wait for MSI stabilization, the MSI clock is - always enabled because it is the fall back clock when PLL the fails. - Trim fields are not altered from reset values.*/ - - /* MSIRANGE can be set only when MSI is OFF or READY.*/ - RCC->CR = RCC_CR_MSION; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; /* Wait until MSI is stable. */ - - /* Clocking from MSI, in case MSI was not the default source.*/ - RCC->CFGR = 0; - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) - ; /* Wait until MSI is selected. */ - - /* Core voltage setup.*/ - PWR->CR1 = STM32_VOS; - while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ - ; /* stable. */ - - /* Boost mode setting.*/ - PWR->CR5 = STM32_R1MODE; - -#if STM32_HSI16_ENABLED - /* HSI activation.*/ - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Wait until HSI16 is stable. */ -#endif - -#if STM32_HSI48_ENABLED - /* HSI activation.*/ - RCC->CRRCR |= RCC_CRRCR_HSI48ON; - while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) - ; /* Wait until HSI48 is stable. */ -#endif - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Wait until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Wait until LSI is stable. */ -#endif - - /* Backup domain access enabled and left open.*/ - PWR->CR1 |= PWR_CR1_DBP; - -#if STM32_LSE_ENABLED - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Wait until LSE is stable. */ -#endif - - /* Flash setup for selected MSI speed setting.*/ - FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | - STM32_MSI_FLASHBITS; - - /* Changing MSIRANGE to configured value.*/ - RCC->CR |= STM32_MSIRANGE; - - /* Switching from MSISRANGE to MSIRANGE.*/ - RCC->CR |= RCC_CR_MSIRGSEL; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; - - /* MSI is configured SYSCLK source so wait for it to be stable as well.*/ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) - ; - -#if STM32_MSIPLL_ENABLED - /* MSI PLL (to LSE) activation */ - RCC->CR |= RCC_CR_MSIPLLEN; -#endif - - /* Updating MSISRANGE value. MSISRANGE can be set only when MSIRGSEL is high. - This range is used exiting the Standby mode until MSIRGSEL is set.*/ - RCC->CSR |= STM32_MSISRANGE; - -#if STM32_ACTIVATE_PLL || STM32_ACTIVATE_PLLSAI1 || STM32_ACTIVATE_PLLSAI2 - /* PLLM and PLLSRC are common to all PLLs.*/ - RCC->PLLCFGR = STM32_PLLPDIV | STM32_PLLR | - STM32_PLLREN | STM32_PLLQ | - STM32_PLLQEN | STM32_PLLP | - STM32_PLLPEN | STM32_PLLN | - STM32_PLLM | STM32_PLLSRC; -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLRDY) == 0) - ; -#endif - -#if STM32_ACTIVATE_PLLSAI1 - /* PLLSAI1 activation.*/ - RCC->PLLSAI1CFGR = STM32_PLLSAI1PDIV | STM32_PLLSAI1R | - STM32_PLLSAI1REN | STM32_PLLSAI1Q | - STM32_PLLSAI1QEN | STM32_PLLSAI1P | - STM32_PLLSAI1PEN | STM32_PLLSAI1N | - STM32_PLLSAI1M; - RCC->CR |= RCC_CR_PLLSAI1ON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLSAI1RDY) == 0) - ; -#endif - -#if STM32_ACTIVATE_PLLSAI2 - /* PLLSAI2 activation.*/ - RCC->PLLSAI2CFGR = STM32_PLLSAI2PDIV | STM32_PLLSAI2R | - STM32_PLLSAI2REN | STM32_PLLSAI2P | - STM32_PLLSAI2PEN | STM32_PLLSAI2N | - STM32_PLLSAI2M; - RCC->CR |= RCC_CR_PLLSAI2ON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0) - ; -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_STOPWUCK | - STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - - /* CCIPR register initialization.*/ - { - uint32_t ccipr = STM32_ADCSEL | - STM32_CLK48SEL | STM32_LPTIM2SEL | STM32_LPTIM1SEL | - STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | - STM32_LPUART1SEL | STM32_UART5SEL | STM32_UART4SEL | - STM32_USART3SEL | STM32_USART2SEL | STM32_USART1SEL; - RCC->CCIPR = ccipr; - } - - /* CCIPR2 register initialization, note, must take care of the _OFF - pseudo settings.*/ - { - uint32_t ccipr = STM32_OSPISEL | STM32_PLLSAI2DIVR | - STM32_SDMMCSEL | STM32_DSISEL | STM32_ADFSDMSEL | - STM32_DFSDMSEL | STM32_I2C4SEL; -#if STM32_SAI2SEL != STM32_SAI2SEL_OFF - ccipr |= STM32_SAI2SEL; -#endif -#if STM32_SAI1SEL != STM32_SAI1SEL_OFF - ccipr |= STM32_SAI1SEL; -#endif - RCC->CCIPR2 = ccipr; - } - - /* Set flash WS's for SYSCLK source */ - if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) { - FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - } - - /* Switching to the configured SYSCLK source if it is different from MSI.*/ -#if (STM32_SW != STM32_SW_MSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - /* Wait until SYSCLK is stable.*/ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif - - /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */ - if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) { - FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - } - -#endif /* STM32_NO_INIT */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/hal_lld.c + * @brief STM32L4xx+ HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32l4xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing RTC clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int rusefiLseCounter = 0; + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if STM32_MSIPLL_ENABLED + /* MSI PLL activation depends on LSE. Reactivating and checking for + MSI stability.*/ + RCC->CR |= RCC_CR_MSIPLLEN; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; /* Wait until MSI is stable. */ +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + + /* Low speed output mode.*/ + RCC->BDCR |= STM32_LSCOSEL; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~0); + rccResetAHB2(~STM32_GPIO_EN_MASK); + rccResetAHB3(~0); + rccResetAPB1R1(~RCC_APB1RSTR1_PWRRST); + rccResetAPB1R2(~0); + rccResetAPB2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK); +#else + PWR->CR2 = 0; +#endif /* STM32_PVD_ENABLE */ + + /* Enabling independent VDDUSB.*/ +#if HAL_USE_USB + PWR->CR2 |= PWR_CR2_USV; +#endif /* HAL_USE_USB */ + + /* Enabling independent VDDIO2 required by GPIOG.*/ +#if STM32_HAS_GPIOG + PWR->CR2 |= PWR_CR2_IOSV; +#endif /* STM32_HAS_GPIOG */ +} + +/** + * @brief STM32L4xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ +#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR1_RTCAPBEN) + RCC->APB1ENR1 = RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN; +#else + RCC->APB1ENR1 = RCC_APB1ENR1_PWREN; +#endif + + /* Initial clocks setup and wait for MSI stabilization, the MSI clock is + always enabled because it is the fall back clock when PLL the fails. + Trim fields are not altered from reset values.*/ + + /* MSIRANGE can be set only when MSI is OFF or READY.*/ + RCC->CR = RCC_CR_MSION; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; /* Wait until MSI is stable. */ + + /* Clocking from MSI, in case MSI was not the default source.*/ + RCC->CFGR = 0; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + ; /* Wait until MSI is selected. */ + + /* Core voltage setup.*/ + PWR->CR1 = STM32_VOS; + while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ + ; /* stable. */ + + /* Boost mode setting.*/ + PWR->CR5 = STM32_R1MODE; + +#if STM32_HSI16_ENABLED + /* HSI activation.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Wait until HSI16 is stable. */ +#endif + +#if STM32_HSI48_ENABLED + /* HSI activation.*/ + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) + ; /* Wait until HSI48 is stable. */ +#endif + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Wait until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Wait until LSI is stable. */ +#endif + + /* Backup domain access enabled and left open.*/ + PWR->CR1 |= PWR_CR1_DBP; + +#if STM32_LSE_ENABLED + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Wait until LSE is stable. */ +#endif + + /* Flash setup for selected MSI speed setting.*/ + FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | + STM32_MSI_FLASHBITS; + + /* Changing MSIRANGE to configured value.*/ + RCC->CR |= STM32_MSIRANGE; + + /* Switching from MSISRANGE to MSIRANGE.*/ + RCC->CR |= RCC_CR_MSIRGSEL; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; + + /* MSI is configured SYSCLK source so wait for it to be stable as well.*/ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + ; + +#if STM32_MSIPLL_ENABLED + /* MSI PLL (to LSE) activation */ + RCC->CR |= RCC_CR_MSIPLLEN; +#endif + + /* Updating MSISRANGE value. MSISRANGE can be set only when MSIRGSEL is high. + This range is used exiting the Standby mode until MSIRGSEL is set.*/ + RCC->CSR |= STM32_MSISRANGE; + +#if STM32_ACTIVATE_PLL || STM32_ACTIVATE_PLLSAI1 || STM32_ACTIVATE_PLLSAI2 + /* PLLM and PLLSRC are common to all PLLs.*/ + RCC->PLLCFGR = STM32_PLLPDIV | STM32_PLLR | + STM32_PLLREN | STM32_PLLQ | + STM32_PLLQEN | STM32_PLLP | + STM32_PLLPEN | STM32_PLLN | + STM32_PLLM | STM32_PLLSRC; +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLRDY) == 0) + ; +#endif + +#if STM32_ACTIVATE_PLLSAI1 + /* PLLSAI1 activation.*/ + RCC->PLLSAI1CFGR = STM32_PLLSAI1PDIV | STM32_PLLSAI1R | + STM32_PLLSAI1REN | STM32_PLLSAI1Q | + STM32_PLLSAI1QEN | STM32_PLLSAI1P | + STM32_PLLSAI1PEN | STM32_PLLSAI1N | + STM32_PLLSAI1M; + RCC->CR |= RCC_CR_PLLSAI1ON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLSAI1RDY) == 0) + ; +#endif + +#if STM32_ACTIVATE_PLLSAI2 + /* PLLSAI2 activation.*/ + RCC->PLLSAI2CFGR = STM32_PLLSAI2PDIV | STM32_PLLSAI2R | + STM32_PLLSAI2REN | STM32_PLLSAI2P | + STM32_PLLSAI2PEN | STM32_PLLSAI2N | + STM32_PLLSAI2M; + RCC->CR |= RCC_CR_PLLSAI2ON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0) + ; +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_STOPWUCK | + STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + + /* CCIPR register initialization.*/ + { + uint32_t ccipr = STM32_ADCSEL | + STM32_CLK48SEL | STM32_LPTIM2SEL | STM32_LPTIM1SEL | + STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | + STM32_LPUART1SEL | STM32_UART5SEL | STM32_UART4SEL | + STM32_USART3SEL | STM32_USART2SEL | STM32_USART1SEL; + RCC->CCIPR = ccipr; + } + + /* CCIPR2 register initialization, note, must take care of the _OFF + pseudo settings.*/ + { + uint32_t ccipr = STM32_OSPISEL | STM32_PLLSAI2DIVR | + STM32_SDMMCSEL | STM32_DSISEL | STM32_ADFSDMSEL | + STM32_DFSDMSEL | STM32_I2C4SEL; +#if STM32_SAI2SEL != STM32_SAI2SEL_OFF + ccipr |= STM32_SAI2SEL; +#endif +#if STM32_SAI1SEL != STM32_SAI1SEL_OFF + ccipr |= STM32_SAI1SEL; +#endif + RCC->CCIPR2 = ccipr; + } + + /* Set flash WS's for SYSCLK source */ + if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) { + FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + } + + /* Switching to the configured SYSCLK source if it is different from MSI.*/ +#if (STM32_SW != STM32_SW_MSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + /* Wait until SYSCLK is stable.*/ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif + + /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */ + if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) { + FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + } + +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/hal_lld.h b/os/hal/ports/STM32/STM32L4xx+/hal_lld.h index 1b16e26561..78877b61ea 100644 --- a/os/hal/ports/STM32/STM32L4xx+/hal_lld.h +++ b/os/hal/ports/STM32/STM32L4xx+/hal_lld.h @@ -1,2614 +1,2622 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/hal_lld.h - * @brief STM32L4xx+ 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32L4R5xx, STM32L4R7xx, STM32L4R9xx. - * - STM32L4S5xx, STM32L4S7xx, STM32L4S9xx. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || \ - defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32L4+ Ultra Low Power" - -#elif defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) -#define PLATFORM_NAME "STM32L4+ Ultra Low Power with Crypto" - -#else -#error "STM32L4+ device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32L4XXP) || defined(__DOXYGEN__) -#define STM32L4XXP -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ -#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR1 register bits definitions - * @{ - */ -#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */ -#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */ -#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ -/** @} */ - -/** - * @name PWR_CR2 register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ -#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CR register bits definitions - * @{ - */ -#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */ -#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */ -#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */ -#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */ -#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */ -#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */ -#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */ -#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */ -#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */ -#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */ -#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */ -#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */ -#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ -#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ -#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */ -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */ -#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */ -#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */ - -#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ -#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ - -#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ -#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ -#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ -#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ -#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ -#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */ -#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CCIPR register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ -#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ -#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ -#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */ -#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ - -#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ -#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ -#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ -#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */ -#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ - -#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ -#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ -#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ -#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */ -#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ - -#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ -#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ -#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ -#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */ -#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ - -#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ -#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ -#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ -#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */ -#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ - -#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */ -#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */ -#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */ -#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */ -#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */ - -#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */ -#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */ - -#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */ -#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */ -#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */ -#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */ - -#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */ -#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */ -#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */ -#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */ - -#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */ -#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */ -#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */ -#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */ - -#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */ -#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */ -#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */ -#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */ -#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */ - -#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */ -#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */ -#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */ -#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */ -#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */ - -#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */ -#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */ -#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */ -#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */ -/** @} */ - -/** - * @name RCC_CCIPR2 register bits definitions - * @{ - */ -#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */ -#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */ -#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */ - -#define STM32_DFSDMSEL_MASK (1 << 2) /**< DFSDMSEL mask. */ -#define STM32_DFSDMSEL_PCLK2 (0 << 2) /**< DFSDMSEL source is PCLK2. */ -#define STM32_DFSDMSEL_SYSCLK (1 << 2) /**< DFSDMSEL source is SYSCLK. */ - -#define STM32_ADFSDMSEL_MASK (3 << 3) /**< ADFSDMSEL mask. */ -#define STM32_ADFSDMSEL_SAI1CLK (0 << 3) /**< ADFSDMSEL source is - SAI1CLK. */ -#define STM32_ADFSDMSEL_HSI16 (1 << 3) /**< ADFSDMSEL source is HSI16. */ -#define STM32_ADFSDMSEL_MSI (2 << 3) /**< ADFSDMSEL source is MSI. */ - -#define STM32_SAI1SEL_MASK (7 << 5) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_PLLSAI1 (0 << 5) /**< SAI1 source is PLLSAI1CLK. */ -#define STM32_SAI1SEL_PLLSAI2 (1 << 5) /**< SAI1 source is PLLSAI2CLK. */ -#define STM32_SAI1SEL_PLL (2 << 5) /**< SAI1 source is PLLSAI3CLK */ -#define STM32_SAI1SEL_EXTCLK (3 << 5) /**< SAI1 source is external. */ -#define STM32_SAI1SEL_HSI16 (4 << 5) /**< SAI1 source is HSI16. */ -#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ - -#define STM32_SAI2SEL_MASK (7 << 8) /**< SAI2SEL mask. */ -#define STM32_SAI2SEL_PLLSAI1 (0 << 8) /**< SAI2 source is PLLSAI1CLK. */ -#define STM32_SAI2SEL_PLLSAI2 (1 << 8) /**< SAI2 source is PLLSAI2CLK. */ -#define STM32_SAI2SEL_PLL (2 << 8) /**< SAI2 source is PLLSAI3CLK */ -#define STM32_SAI2SEL_EXTCLK (3 << 8) /**< SAI2 source is external. */ -#define STM32_SAI2SEL_HSI16 (4 << 8) /**< SAI2 source is HSI16. */ -#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ - -#define STM32_DSISEL_MASK (1 << 12) /**< DSISE mask. */ -#define STM32_DSISEL_DSIPHY (0 << 12) /**< DSISE source is DSIPHY. */ -#define STM32_DSISEL_PLLDSICLK (1 << 12) /**< DSISE source is PLLDSICLK. */ - -#define STM32_SDMMCSEL_MASK (1 << 14) /**< SDMMCSEL mask. */ -#define STM32_SDMMCSEL_48CLK (0 << 14) /**< SDMMCSEL source is 48CLK. */ -#define STM32_SDMMCSEL_PLLSAI3CLK (1 << 14) /**< SDMMCSEL source is - PLLSAI3CLK. */ - -#define STM32_PLLSAI2DIVR_MASK (3 << 16) /**< PLLSAI2DIVR mask. */ -#define STM32_PLLSAI2DIVR_DIV2 (0 << 16) /**< PLLSAI2_R divided by 2. */ -#define STM32_PLLSAI2DIVR_DIV4 (1 << 16) /**< PLLSAI2_R divided by 4. */ -#define STM32_PLLSAI2DIVR_DIV8 (2 << 16) /**< PLLSAI2_R divided by 8. */ -#define STM32_PLLSAI2DIVR_DIV16 (3 << 16) /**< PLLSAI2_R divided by 16. */ - -#define STM32_OSPISEL_MASK (3 << 20) /**< OSPISEL mask. */ -#define STM32_OSPISEL_SYSCLK (0 << 20) /**< OSPI source is SYSCLK. */ -#define STM32_OSPISEL_MSI (1 << 20) /**< OSPI source is MSI. */ -#define STM32_OSPISEL_48CLK (2 << 20) /**< OSPI source is 48CLK. */ -/** @} */ - -/** - * @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. */ - -#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */ -#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */ -#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */ -#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */ -/** @} */ - -/** - * @name RCC_CSR register bits definitions - * @{ - */ -#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */ -#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */ -#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */ -#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */ -#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_RANGE1 -#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 HSI16 clock source. - */ -#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSI48 clock source. - */ -#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI48_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief Enables or disables the MSI PLL on LSE clock source. - */ -#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__) -#define STM32_MSIPLL_ENABLED FALSE -#endif - -/** - * @brief MSI frequency setting. - */ -#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) -#define STM32_MSIRANGE STM32_MSIRANGE_4M -#endif - -/** - * @brief MSI frequency setting after standby. - */ -#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__) -#define STM32_MSISRANGE STM32_MSISRANGE_4M -#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 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @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 internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_MSI -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 1 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 8..127. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 60 -#endif - -/** - * @brief PLLPDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLPDIV_VALUE 0 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 7 -#endif - -/** - * @brief PLLQ divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 4 -#endif - -/** - * @brief PLLR divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLR_VALUE 2 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief STOPWUCK clock setting. - */ -#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) -#define STM32_STOPWUCK STM32_STOPWUCK_MSI -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief LSCO clock source. - */ -#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#endif - -/** - * @brief PLLSAI1M divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSAI1M_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1M_VALUE 1 -#endif - -/** - * @brief PLLSAI1N multiplier value. - * @note The allowed values are 8..127. - */ -#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1N_VALUE 72 -#endif - -/** - * @brief PLLSAI1PDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1PDIV_VALUE 6 -#endif - -/** - * @brief PLLSAI1P divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1P_VALUE 7 -#endif - -/** - * @brief PLLSAI1Q divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1Q_VALUE 6 -#endif - -/** - * @brief PLLSAI1R divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1R_VALUE 6 -#endif - -/** - * @brief PLLSAI2M divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSAI2M_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2M_VALUE 1 -#endif - -/** - * @brief PLLSAI2N multiplier value. - * @note The allowed values are 8..127. - */ -#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2N_VALUE 72 -#endif - -/** - * @brief PLLSAI2PDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2PDIV_VALUE 6 -#endif - -/** - * @brief PLLSAI2P divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2P_VALUE 7 -#endif - -/** - * @brief PLLSAI2Q divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI2Q_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2Q_VALUE 6 -#endif - -/** - * @brief PLLSAI2R divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2R_VALUE 6 -#endif - -/** - * @brief PLLSAI2DIVR value. - */ -#if !defined(STM32_PLLSAI2DIVR) || defined(__DOXYGEN__) -#define STM32_PLLSAI2DIVR STM32_PLLSAI2DIVR_DIV16 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) -#define STM32_UART5SEL STM32_UART5SEL_SYSCLK -#endif - -/** - * @brief LPUART1 clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) -#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK -#endif - -/** - * @brief I2C3 clock source. - */ -#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) -#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK -#endif - -/** - * @brief I2C4 clock source. - */ -#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) -#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#endif - -/** - * @brief LPTIM2 clock source. - */ -#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 -#endif - -/** - * @brief CLK48SEL value (48MHz clock source). - */ -#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) -#define STM32_CLK48SEL STM32_CLK48SEL_PLL -#endif - -/** - * @brief ADCSEL value (ADCs clock source). - */ -#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) -#define STM32_ADCSEL STM32_ADCSEL_SYSCLK -#endif - -/** - * @brief DFSDMSEL value (DFSDM clock source). - */ -#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__) -#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 -#endif - -/** - * @brief ADFSDMSEL value (DFSDM clock source). - */ -#if !defined(STM32_ADFSDMSEL) || defined(__DOXYGEN__) -#define STM32_ADFSDMSEL STM32_ADFSDMSEL_SAI1CLK -#endif - -/** - * @brief SAI1SEL value (SAI1 clock source). - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#endif - -/** - * @brief SAI2SEL value (SAI2 clock source). - */ -#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#endif - -/** - * @brief DSISEL value (DSI clock source). - */ -#if !defined(STM32_DSISEL) || defined(__DOXYGEN__) -#define STM32_DSISEL STM32_DSISEL_DSIPHY -#endif - -/** - * @brief SDMMC value (SDMMC clock source). - */ -#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__) -#define STM32_SDMMCSEL STM32_SDMMCSEL_48CLK -#endif - -/** - * @brief OSPISEL value (OSPISEL clock source). - */ -#if !defined(STM32_OSPISEL) || defined(__DOXYGEN__) -#define STM32_OSPISEL STM32_OSPISEL_SYSCLK -#endif - -/** - * @brief RTC/LCD clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32L4xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4xx_MCUCONF not defined" -#endif - -#if defined(STM32L4R5xx) && !defined(STM32L4R5_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4R5_MCUCONF not defined" - -#elif defined(STM32L4S5xx) && !defined(STM32L4S5_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4S5_MCUCONF not defined" - -#elif defined(STM32L4R7xx) && !defined(STM32L4R7_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4R7_MCUCONF not defined" - -#elif defined(STM32L4S7xx) && !defined(STM32L4S7_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4S7_MCUCONF not defined" - -#elif defined(STM32L4R9xx) && !defined(STM32L4R9_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4R9_MCUCONF not defined" - -#elif defined(STM32L4S9xx) && !defined(STM32L4S9_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4S9_MCUCONF not defined" - -#endif - -/* - * Board files sanity checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif - -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) -/** - * @name System Limits - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency in boost mode. - */ -#define STM32_SYSCLK_MAX 120000000 - -/** - * @brief Maximum SYSCLK clock frequency in normal mode. - */ -#define STM32_SYSCLK_NOBOOST_MAX 80000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 48000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 8000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 8000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 2660000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 344000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 64000000 - -/** - * @brief Maximum PLL-P output clock frequency. - */ -#define STM32_PLLP_MAX 120000000 - -/** - * @brief Minimum PLL-P output clock frequency. - */ -#define STM32_PLLP_MIN 2064500 - -/** - * @brief Maximum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MAX 120000000 - -/** - * @brief Minimum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MIN 8000000 - -/** - * @brief Maximum PLL-R output clock frequency. - */ -#define STM32_PLLR_MAX 120000000 - -/** - * @brief Minimum PLL-R output clock frequency. - */ -#define STM32_PLLR_MIN 8000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 120000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 120000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 80000000 -/** @} */ - -/** - * @name Flash Wait states - * @{ - */ -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 120000000 -/** @} */ - -#elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 26000000 -#define STM32_SYSCLK_NOBOOST_MAX 26000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 26000000 -#define STM32_HSECLK_MIN 8000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2660000 -#define STM32_PLLVCO_MAX 128000000 -#define STM32_PLLVCO_MIN 64000000 -#define STM32_PLLP_MAX 26000000 -#define STM32_PLLP_MIN 2064500 -#define STM32_PLLQ_MAX 26000000 -#define STM32_PLLQ_MIN 8000000 -#define STM32_PLLR_MAX 26000000 -#define STM32_PLLR_MIN 8000000 -#define STM32_PCLK1_MAX 26000000 -#define STM32_PCLK2_MAX 26000000 -#define STM32_ADCCLK_MAX 26000000 - -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_1WS_THRESHOLD 16000000 -#define STM32_2WS_THRESHOLD 26000000 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 - -#else -#error "invalid STM32_VOS value specified" -#endif - -/** - * @brief MSI frequency. - */ -#if STM32_MSIRANGE == STM32_MSIRANGE_100K -#define STM32_MSICLK 100000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_200K -#define STM32_MSICLK 200000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_400K -#define STM32_MSICLK 400000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_800K -#define STM32_MSICLK 800000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_1M -#define STM32_MSICLK 1000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_2M -#define STM32_MSICLK 2000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_4M -#define STM32_MSICLK 4000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_8M -#define STM32_MSICLK 8000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_16M -#define STM32_MSICLK 16000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_24M -#define STM32_MSICLK 24000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_32M -#define STM32_MSICLK 32000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_48M -#define STM32_MSICLK 48000000 -#else -#error "invalid STM32_MSIRANGE value specified" -#endif - -/** - * @brief MSIS frequency. - */ -#if STM32_MSISRANGE == STM32_MSISRANGE_1M -#define STM32_MSISCLK 1000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_2M -#define STM32_MSISCLK 2000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_4M -#define STM32_MSISCLK 4000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_8M -#define STM32_MSISCLK 8000000 -#else -#error "invalid STM32_MSISRANGE value specified" -#endif - -/* - * HSI16 related checks. - */ -#if STM32_HSI16_ENABLED -#else /* !STM32_HSI16_ENABLED */ - -#if STM32_SW == STM32_SW_HSI16 -#error "HSI16 not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -/* NOTE: Missing checks on the HSI16 pre-muxes, it is also required for newer - L4 devices.*/ - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16)) -#error "HSI16 not enabled, required by STM32_MCOSEL" -#endif - -#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SAI1SEL" -#endif - -#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SAI2SEL" -#endif - -#if (STM32_USART1SEL == STM32_USART1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART1SEL" -#endif -#if (STM32_USART2SEL == STM32_USART2SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART2SEL" -#endif -#if (STM32_USART3SEL == STM32_USART3SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART3SEL" -#endif -#if (STM32_UART4SEL == STM32_UART4SEL_HSI16) -#error "HSI16 not enabled, required by STM32_UART4SEL" -#endif -#if (STM32_UART5SEL == STM32_UART5SEL_HSI16) -#error "HSI16 not enabled, required by STM32_UART5SEL" -#endif -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_LPUART1SEL" -#endif - -#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) -#error "HSI16 not enabled, required by I2C1SEL" -#endif -#if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) -#error "HSI16 not enabled, required by I2C2SEL" -#endif -#if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) -#error "HSI16 not enabled, required by I2C3SEL" -#endif -#if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) -#error "HSI16 not enabled, required by I2C4SEL" -#endif - -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) -#error "HSI16 not enabled, required by LPTIM1SEL" -#endif -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) -#error "HSI16 not enabled, required by LPTIM2SEL" -#endif - -#if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16) -#error "HSI16 not enabled, required by STM32_STOPWUCK" -#endif - -#endif /* !STM32_HSI16_ENABLED */ - -#if STM32_HSI48_ENABLED -#else /* !STM32_HSI48_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_HSI48 -#error "HSI48 not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 -#error "HSI48 not enabled, required by STM32_CLK48SEL" -#endif -#endif /* !STM32_HSI48_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - - #if STM32_HSECLK == 0 - #error "HSE frequency not defined" - #else /* STM32_HSECLK != 0 */ - #if defined(STM32_HSE_BYPASS) - #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" - #endif - #else /* !defined(STM32_HSE_BYPASS) */ - #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" - #endif - #endif /* !defined(STM32_HSE_BYPASS) */ - #endif /* STM32_HSECLK != 0 */ - - #else /* !STM32_HSE_ENABLED */ - - #if STM32_SW == STM32_SW_HSE - #error "HSE not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) - #error "HSE not enabled, required by STM32_MCOSEL" - #endif - - #if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) | \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SAI1SEL" - #endif - - #if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) | \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SAI2SEL" - #endif - - #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV - #error "HSE not enabled, required by STM32_RTCSEL" - #endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - - #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) - #error "LSI not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSI - #error "LSI not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSI - #error "LSI not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - - #if (STM32_LSECLK == 0) - #error "LSE frequency not defined" - #endif - - #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) - #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" - #endif - -#else /* !STM32_LSE_ENABLED */ - - #if STM32_RTCSEL == STM32_RTCSEL_LSE - #error "LSE not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSE - #error "LSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSE - #error "LSE not enabled, required by STM32_LSCOSEL" - #endif - - #if STM32_MSIPLL_ENABLED == TRUE - #error "LSE not enabled, required by STM32_MSIPLL_ENABLED" - #endif - -#endif /* !STM32_LSE_ENABLED */ - -/* - * MSI related checks. - */ -#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED -#warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED" -#endif - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) -#else -#error "invalid STM32_PLLM_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_MSI -#define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 -#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK -#define STM32_PLLCLKIN 0 - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLL input frequency range check. - */ -#if (STM32_PLLCLKIN != 0) && \ - ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ - defined(__DOXYGEN__) - -#if STM32_PLLCLKIN == 0 -#error "PLL activation required but no PLL clock selected" -#endif - -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 8) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLP (0 << 17) - -#elif STM32_PLLP_VALUE == 17 -#define STM32_PLLP (1 << 17) - -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLQ (0 << 21) - -#elif STM32_PLLQ_VALUE == 4 -#define STM32_PLLQ (1 << 21) - -#elif STM32_PLLQ_VALUE == 6 -#define STM32_PLLQ (2 << 21) - -#elif STM32_PLLQ_VALUE == 8 -#define STM32_PLLQ (3 << 21) - -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLR field. - */ -#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLR (0 << 25) - -#elif STM32_PLLR_VALUE == 4 -#define STM32_PLLR (1 << 25) - -#elif STM32_PLLR_VALUE == 6 -#define STM32_PLLR (2 << 25) - -#elif STM32_PLLR_VALUE == 8 -#define STM32_PLLR (3 << 25) - -#else -#error "invalid STM32_PLLR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLPDIV field. - */ -#if (STM32_PLLPDIV_VALUE == 0) || \ - ((STM32_PLLPDIV_VALUE != 1) && (STM32_PLLPDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) -#else -#error "invalid STM32_PLLPDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLPEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ - defined(__DOXYGEN__) -#define STM32_PLLPEN (1 << 16) -#else -#define STM32_PLLPEN (0 << 16) -#endif - -/** - * @brief STM32_PLLQEN field. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__) -#define STM32_PLLQEN (1 << 20) -#else -#define STM32_PLLQEN (0 << 20) -#endif - -/** - * @brief STM32_PLLREN field. - */ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - defined(__DOXYGEN__) -#define STM32_PLLREN (1 << 24) -#else -#define STM32_PLLREN (0 << 24) -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL P output clock frequency. - */ -#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) -#else -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) -#endif - -/** - * @brief PLL Q output clock frequency. - */ -#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) - -/** - * @brief PLL R output clock frequency. - */ -#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) - -/* - * PLL-P output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLL-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLL-R output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_MSICLK - -#elif (STM32_SW == STM32_SW_MSI) -#define STM32_SYSCLK STM32_MSICLK - -#elif (STM32_SW == STM32_SW_HSI16) -#define STM32_SYSCLK STM32_HSI16CLK - -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK - -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLL_R_CLKOUT - -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) - -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) - -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) - -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) - -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) - -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) - -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) - -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) - -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) - -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief STM32_PLLSAI1M field. - */ -#if ((STM32_PLLSAI1M_VALUE >= 1) && (STM32_PLLSAI1M_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1M ((STM32_PLLSAI1M_VALUE - 1) << 4) -#else -#error "invalid STM32_PLLSAI1M_VALUE value specified" -#endif - -/** - * @brief PLLSAI1 input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1CLKIN (STM32_HSECLK / STM32_PLLSAI1M_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_MSI -#define STM32_PLLSAI1CLKIN (STM32_MSICLK / STM32_PLLSAI1M_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 -#define STM32_PLLSAI1CLKIN (STM32_HSI16CLK / STM32_PLLSAI1M_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK -#define STM32_PLLSAI1CLKIN 0 - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLLSAI1 input frequency range check. - */ -#if (STM32_PLLSAI1CLKIN != 0) && \ - ((STM32_PLLSAI1CLKIN < STM32_PLLIN_MIN) || \ - (STM32_PLLSAI1CLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLSAI1CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLLSAI1 enable check. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \ - (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ - defined(__DOXYGEN__) - -#if STM32_PLLSAI1CLKIN == 0 -#error "PLLSAI1 activation required but no PLL clock selected" -#endif - -/** - * @brief PLLSAI1 activation flag. - */ -#define STM32_ACTIVATE_PLLSAI1 TRUE -#else -#define STM32_ACTIVATE_PLLSAI1 FALSE -#endif - -/** - * @brief STM32_PLLSAI1N field. - */ -#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 127)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8) -#else -#error "invalid STM32_PLLSAI1N_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1P field. - */ -#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLSAI1P (0 << 17) - -#elif STM32_PLLSAI1P_VALUE == 17 -#define STM32_PLLSAI1P (1 << 17) - -#else -#error "invalid STM32_PLLSAI1P_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1Q field. - */ -#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI1Q (0 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 4 -#define STM32_PLLSAI1Q (1 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 6 -#define STM32_PLLSAI1Q (2 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 8 -#define STM32_PLLSAI1Q (3 << 21) - -#else -#error "invalid STM32_PLLSAI1Q_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1R field. - */ -#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI1R (0 << 25) - -#elif STM32_PLLSAI1R_VALUE == 4 -#define STM32_PLLSAI1R (1 << 25) - -#elif STM32_PLLSAI1R_VALUE == 6 -#define STM32_PLLSAI1R (2 << 25) - -#elif STM32_PLLSAI1R_VALUE == 8 -#define STM32_PLLSAI1R (3 << 25) - -#else -#error "invalid STM32_PLLSAI1R_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1PDIV field. - */ -#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27) -#else -#error "invalid STM32_PLLSAI1PDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1PEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1PEN (1 << 16) -#else -#define STM32_PLLSAI1PEN (0 << 16) -#endif - -/** - * @brief STM32_PLLSAI1QEN field. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_PLLSAI1QEN (1 << 20) -#else -#define STM32_PLLSAI1QEN (0 << 20) -#endif - -/** - * @brief STM32_PLLSAI1REN field. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_PLLSAI1REN (1 << 24) -#else -#define STM32_PLLSAI1REN (0 << 24) -#endif - -/** - * @brief PLLSAI1 VCO frequency. - */ -#define STM32_PLLSAI1VCO (STM32_PLLSAI1CLKIN * STM32_PLLSAI1N_VALUE) - -/* - * PLLSAI1 VCO frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI1-P output clock frequency. - */ -#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE) -#else -#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE) -#endif - -/** - * @brief PLLSAI1-Q output clock frequency. - */ -#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) - -/** - * @brief PLLSAI1-R output clock frequency. - */ -#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE) - -/* - * PLLSAI1-P output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLLSAI1-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLLSAI1-R output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief STM32_PLLSAI2M field. - */ -#if ((STM32_PLLSAI2M_VALUE >= 1) && (STM32_PLLSAI2M_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2M ((STM32_PLLSAI2M_VALUE - 1) << 4) -#else -#error "invalid STM32_PLLSAI2M_VALUE value specified" -#endif - -/** - * @brief PLLSAI2 input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2CLKIN (STM32_HSECLK / STM32_PLLSAI2M_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_MSI -#define STM32_PLLSAI2CLKIN (STM32_MSICLK / STM32_PLLSAI2M_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 -#define STM32_PLLSAI2CLKIN (STM32_HSI16CLK / STM32_PLLSAI2M_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK -#define STM32_PLLSAI2CLKIN 0 - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLLSAI2 input frequency range check. - */ -#if (STM32_PLLSAI2CLKIN != 0) && \ - ((STM32_PLLSAI2CLKIN < STM32_PLLIN_MIN) || \ - (STM32_PLLSAI2CLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLSAI2CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLLSAI2 enable check. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ - defined(__DOXYGEN__) - -#if STM32_PLLSAI2CLKIN == 0 -#error "PLLSAI2 activation required but no PLL clock selected" -#endif - -/** - * @brief PLLSAI2 activation flag. - */ -#define STM32_ACTIVATE_PLLSAI2 TRUE -#else -#define STM32_ACTIVATE_PLLSAI2 FALSE -#endif - -/** - * @brief STM32_PLLSAI2N field. - */ -#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 127)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8) -#else -#error "invalid STM32_PLLSAI2N_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2P field. - */ -#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLSAI2P (0 << 17) - -#elif STM32_PLLSAI2P_VALUE == 17 -#define STM32_PLLSAI2P (1 << 17) - -#else -#error "invalid STM32_PLLSAI2P_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2R field. - */ -#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI2R (0 << 25) - -#elif STM32_PLLSAI2R_VALUE == 4 -#define STM32_PLLSAI2R (1 << 25) - -#elif STM32_PLLSAI2R_VALUE == 6 -#define STM32_PLLSAI2R (2 << 25) - -#elif STM32_PLLSAI2R_VALUE == 8 -#define STM32_PLLSAI2R (3 << 25) - -#else -#error "invalid STM32_PLLSAI2R_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2PDIV field. - */ -#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27) -#else -#error "invalid STM32_PLLSAI2PDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2PEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2PEN (1 << 16) -#else -#define STM32_PLLSAI2PEN (0 << 16) -#endif - -/** - * @brief STM32_PLLSAI2REN field. - * @note Always enabled. - * @note It should depend on some condition. - */ -#define STM32_PLLSAI2REN (1 << 24) - -/** - * @brief PLLSAI2 VCO frequency. - */ -#define STM32_PLLSAI2VCO (STM32_PLLSAI2CLKIN * STM32_PLLSAI2N_VALUE) - -/* - * PLLSAI2 VCO frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI2-P output clock frequency. - */ -#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE) -#else -#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE) -#endif - -/** - * @brief PLLSAI2-R output clock frequency. - */ -#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE) - -/* - * PLLSAI2-P output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLLSAI2-R output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief MCO divider clock frequency. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 - -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK -#define STM32_MCODIVCLK STM32_SYSCLK - -#elif STM32_MCOSEL == STM32_MCOSEL_MSI -#define STM32_MCODIVCLK STM32_MSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 -#define STM32_MCODIVCLK STM32_HSI16CLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_PLL -#define STM32_MCODIVCLK STM32_PLL_R_CLKOUT - -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 -#define STM32_MCODIVCLK STM32_HSI48CLK - -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock frequency. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) - -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief RTC clock frequency. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 clock frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK2 - -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK - -#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 -#define STM32_USART1CLK STM32_HSI16CLK - -#elif STM32_USART1SEL == STM32_USART1SEL_LSE -#define STM32_USART1CLK STM32_LSECLK - -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 clock frequency. - */ -#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK1 - -#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK - -#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 -#define STM32_USART2CLK STM32_HSI16CLK - -#elif STM32_USART2SEL == STM32_USART2SEL_LSE -#define STM32_USART2CLK STM32_LSECLK - -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 clock frequency. - */ -#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART3CLK STM32_PCLK1 - -#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK - -#elif STM32_USART3SEL == STM32_USART3SEL_HSI16 -#define STM32_USART3CLK STM32_HSI16CLK - -#elif STM32_USART3SEL == STM32_USART3SEL_LSE -#define STM32_USART3CLK STM32_LSECLK - -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief UART4 clock frequency. - */ -#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART4CLK STM32_PCLK1 - -#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK - -#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 -#define STM32_UART4CLK STM32_HSI16CLK - -#elif STM32_UART4SEL == STM32_UART4SEL_LSE -#define STM32_UART4CLK STM32_LSECLK - -#else -#error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 clock frequency. - */ -#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART5CLK STM32_PCLK1 - -#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK - -#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 -#define STM32_UART5CLK STM32_HSI16CLK - -#elif STM32_UART5SEL == STM32_UART5SEL_LSE -#define STM32_UART5CLK STM32_LSECLK - -#else -#error "invalid source selected for UART5 clock" -#endif - -/** - * @brief LPUART1 clock frequency. - */ -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPUART1CLK STM32_PCLK1 - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK -#define STM32_LPUART1CLK STM32_SYSCLK - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 -#define STM32_LPUART1CLK STM32_HSI16CLK - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE -#define STM32_LPUART1CLK STM32_LSECLK - -#else -#error "invalid source selected for LPUART1 clock" -#endif - -/** - * @brief I2C1 clock frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK1 - -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK - -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 -#define STM32_I2C1CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 clock frequency. - */ -#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C2CLK STM32_PCLK1 - -#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK - -#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 -#define STM32_I2C2CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief I2C3 clock frequency. - */ -#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C3CLK STM32_PCLK1 - -#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK -#define STM32_I2C3CLK STM32_SYSCLK - -#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 -#define STM32_I2C3CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C3 clock" -#endif - -/** - * @brief I2C4 clock frequency. - */ -#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C4CLK STM32_PCLK1 - -#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK -#define STM32_I2C4CLK STM32_SYSCLK - -#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 -#define STM32_I2C4CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C4 clock" -#endif - -/** - * @brief LPTIM1 clock frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK1 - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI -#define STM32_LPTIM1CLK STM32_LSICLK - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 -#define STM32_LPTIM1CLK STM32_HSI16CLK - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE -#define STM32_LPTIM1CLK STM32_LSECLK - -#else -#error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief LPTIM2 clock frequency. - */ -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM2CLK STM32_PCLK1 - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI -#define STM32_LPTIM2CLK STM32_LSICLK - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 -#define STM32_LPTIM2CLK STM32_HSI16CLK - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE -#define STM32_LPTIM2CLK STM32_LSECLK - -#else -#error "invalid source selected for LPTIM2 clock" -#endif - -/** - * @brief 48MHz clock frequency. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) -#define STM32_48CLK STM32_HSI48CLK - -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 -#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) - -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL -#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) - -#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI -#define STM32_48CLK STM32_MSICLK - -#else -#error "invalid source selected for 48CLK clock" -#endif - -/** - * @brief SAI1 clock frequency. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2 -#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL -#define STM32_SAI1CLK STM32_PLL_P_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK -#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ - -#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 -#define STM32_SAI1CLK STM32_HSI16CLK - -#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF -#define STM32_SAI1CLK 0 - -#else -#error "invalid source selected for SAI1 clock" -#endif - -/** - * @brief SAI2 clock frequency. - */ -#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT - -#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2 -#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT - -#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL -#define STM32_SAI2CLK STM32_PLL_P_CLKOUT - -#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK -#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ - -#elif STM32_SAI2SEL == STM32_SAI2SEL_HSI16 -#define STM32_SAI2CLK STM32_HSI16CLK - -#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF -#define STM32_SAI2CLK 0 - -#else -#error "invalid source selected for SAI2 clock" -#endif - -/** - * @brief DSI clock frequency. - */ -#if (STM32_DSISEL == STM32_DSISEL_DSIPHY) || defined(__DOXYGEN__) -#define STM32_DSICLK 0 - -#elif STM32_DSISEL == STM32_DSISEL_PLLDSICLK -#define STM32_DSICLK STM32_PLLSAI2_Q_CLKOUT - -#else -#error "invalid source selected for DSI clock" -#endif - -/** - * @brief SDMMC clock frequency. - */ -#if (STM32_SDMMCSEL == STM32_SDMMCSEL_48CLK) || defined(__DOXYGEN__) -#define STM32_SDMMCCLK STM32_48CLK - -#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLLSAI3CLK -#define STM32_SDMMCCLK STM32_PLL_P_CLKOUT - -#else -#error "invalid source selected for SDMMC clock" -#endif - -/** - * @brief USB clock point. - */ -#define STM32_USBCLK STM32_48CLK - -/** - * @brief RNG clock point. - */ -#define STM32_RNGCLK STM32_48CLK - -/** - * @brief ADC clock frequency. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__) -#define STM32_ADCCLK 0 - -#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1 -#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT - -#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK -#define STM32_ADCCLK STM32_SYSCLK - -#else -#error "invalid source selected for ADC clock" -#endif - -/** - * @brief DFSDM clock frequency. - */ -#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_DFSDMCLK STM32_PCLK2 - -#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK -#define STM32_DFSDMCLK STM32_SYSCLK - -#else -#error "invalid source selected for DFSDM clock" -#endif - -/** - * @brief SDMMC frequency. - */ -#define STM32_SDMMC1CLK STM32_48CLK - -/** - * @brief LTDC frequency. - */ -#if (STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV2) || defined(__DOXYGEN__) -#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 2) - -#elif STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV4 -#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 4) - -#elif STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV8 -#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 8) - -#elif STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV16 -#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 16) - -#else -#error "invalid STM32_PLLSAI2DIVR value specified" -#endif - -/** - * @brief OSPI clock frequency. - */ -#if (STM32_OSPISEL == STM32_OSPISEL_SYSCLK) || defined(__DOXYGEN__) -#define STM32_OSPICLK STM32_SYSCLK - -#elif STM32_OSPISEL == STM32_OSPISEL_MSI -#define STM32_OSPICLK STM32_MSICLK - -#elif STM32_OSPISEL == STM32_OSPISEL_48CLK -#define STM32_OSPICLK STM32_PLLSAI1_Q_CLKOUT - -#else -#error "invalid source selected for OSPI clock" -#endif - -/** - * @brief Clock of timers connected to APB1 - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Clock of timers connected to APB2. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Voltage boost settings. - */ -#if (STM32_SYSCLK <= STM32_SYSCLK_NOBOOST_MAX) || defined(__DOXYGEN__) -#define STM32_R1MODE PWR_CR5_R1MODE -#else -#define STM32_R1MODE 0 -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS - -#else -#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS -#endif - -/** - * @brief Flash settings for MSI. - */ -#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_MSICLK <= STM32_1WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_MSICLK <= STM32_2WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_MSICLK <= STM32_3WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS - -#else -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/hal_lld.h + * @brief STM32L4xx+ 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32L4R5xx, STM32L4R7xx, STM32L4R9xx. + * - STM32L4S5xx, STM32L4S7xx, STM32L4S9xx. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || \ + defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32L4+ Ultra Low Power" + +#elif defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define PLATFORM_NAME "STM32L4+ Ultra Low Power with Crypto" + +#else +#error "STM32L4+ device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32L4XXP) || defined(__DOXYGEN__) +#define STM32L4XXP +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ +#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR1 register bits definitions + * @{ + */ +#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */ +#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */ +#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ +/** @} */ + +/** + * @name PWR_CR2 register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ +#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CR register bits definitions + * @{ + */ +#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */ +#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */ +#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */ +#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */ +#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */ +#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */ +#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */ +#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */ +#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */ +#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */ +#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */ +#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */ +#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ +#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ +#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */ +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */ +#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */ +#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */ + +#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ +#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ + +#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ +#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ +#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ +#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ +#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ +#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */ +#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CCIPR register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ +#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ +#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ +#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */ +#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ + +#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ +#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ +#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ +#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */ +#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ + +#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ +#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ +#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ +#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */ +#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ + +#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ +#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ +#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ +#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */ +#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ + +#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ +#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ +#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ +#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */ +#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ + +#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */ +#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */ +#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */ +#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */ +#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */ + +#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */ +#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */ + +#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */ +#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */ +#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */ +#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */ + +#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */ +#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */ +#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */ +#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */ + +#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */ +#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */ +#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */ +#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */ + +#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */ +#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */ +#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */ +#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */ +#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */ + +#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */ +#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */ +#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */ +#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */ +#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */ + +#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */ +#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */ +#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */ +#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */ +/** @} */ + +/** + * @name RCC_CCIPR2 register bits definitions + * @{ + */ +#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */ +#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */ +#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */ + +#define STM32_DFSDMSEL_MASK (1 << 2) /**< DFSDMSEL mask. */ +#define STM32_DFSDMSEL_PCLK2 (0 << 2) /**< DFSDMSEL source is PCLK2. */ +#define STM32_DFSDMSEL_SYSCLK (1 << 2) /**< DFSDMSEL source is SYSCLK. */ + +#define STM32_ADFSDMSEL_MASK (3 << 3) /**< ADFSDMSEL mask. */ +#define STM32_ADFSDMSEL_SAI1CLK (0 << 3) /**< ADFSDMSEL source is + SAI1CLK. */ +#define STM32_ADFSDMSEL_HSI16 (1 << 3) /**< ADFSDMSEL source is HSI16. */ +#define STM32_ADFSDMSEL_MSI (2 << 3) /**< ADFSDMSEL source is MSI. */ + +#define STM32_SAI1SEL_MASK (7 << 5) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_PLLSAI1 (0 << 5) /**< SAI1 source is PLLSAI1CLK. */ +#define STM32_SAI1SEL_PLLSAI2 (1 << 5) /**< SAI1 source is PLLSAI2CLK. */ +#define STM32_SAI1SEL_PLL (2 << 5) /**< SAI1 source is PLLSAI3CLK */ +#define STM32_SAI1SEL_EXTCLK (3 << 5) /**< SAI1 source is external. */ +#define STM32_SAI1SEL_HSI16 (4 << 5) /**< SAI1 source is HSI16. */ +#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ + +#define STM32_SAI2SEL_MASK (7 << 8) /**< SAI2SEL mask. */ +#define STM32_SAI2SEL_PLLSAI1 (0 << 8) /**< SAI2 source is PLLSAI1CLK. */ +#define STM32_SAI2SEL_PLLSAI2 (1 << 8) /**< SAI2 source is PLLSAI2CLK. */ +#define STM32_SAI2SEL_PLL (2 << 8) /**< SAI2 source is PLLSAI3CLK */ +#define STM32_SAI2SEL_EXTCLK (3 << 8) /**< SAI2 source is external. */ +#define STM32_SAI2SEL_HSI16 (4 << 8) /**< SAI2 source is HSI16. */ +#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ + +#define STM32_DSISEL_MASK (1 << 12) /**< DSISE mask. */ +#define STM32_DSISEL_DSIPHY (0 << 12) /**< DSISE source is DSIPHY. */ +#define STM32_DSISEL_PLLDSICLK (1 << 12) /**< DSISE source is PLLDSICLK. */ + +#define STM32_SDMMCSEL_MASK (1 << 14) /**< SDMMCSEL mask. */ +#define STM32_SDMMCSEL_48CLK (0 << 14) /**< SDMMCSEL source is 48CLK. */ +#define STM32_SDMMCSEL_PLLSAI3CLK (1 << 14) /**< SDMMCSEL source is + PLLSAI3CLK. */ + +#define STM32_PLLSAI2DIVR_MASK (3 << 16) /**< PLLSAI2DIVR mask. */ +#define STM32_PLLSAI2DIVR_DIV2 (0 << 16) /**< PLLSAI2_R divided by 2. */ +#define STM32_PLLSAI2DIVR_DIV4 (1 << 16) /**< PLLSAI2_R divided by 4. */ +#define STM32_PLLSAI2DIVR_DIV8 (2 << 16) /**< PLLSAI2_R divided by 8. */ +#define STM32_PLLSAI2DIVR_DIV16 (3 << 16) /**< PLLSAI2_R divided by 16. */ + +#define STM32_OSPISEL_MASK (3 << 20) /**< OSPISEL mask. */ +#define STM32_OSPISEL_SYSCLK (0 << 20) /**< OSPI source is SYSCLK. */ +#define STM32_OSPISEL_MSI (1 << 20) /**< OSPI source is MSI. */ +#define STM32_OSPISEL_48CLK (2 << 20) /**< OSPI source is 48CLK. */ +/** @} */ + +/** + * @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. */ + +#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */ +#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */ +#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */ +#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */ +/** @} */ + +/** + * @name RCC_CSR register bits definitions + * @{ + */ +#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */ +#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */ +#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */ +#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */ +#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_RANGE1 +#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 HSI16 clock source. + */ +#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSI48 clock source. + */ +#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI48_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief Enables or disables the MSI PLL on LSE clock source. + */ +#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__) +#define STM32_MSIPLL_ENABLED FALSE +#endif + +/** + * @brief MSI frequency setting. + */ +#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) +#define STM32_MSIRANGE STM32_MSIRANGE_4M +#endif + +/** + * @brief MSI frequency setting after standby. + */ +#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__) +#define STM32_MSISRANGE STM32_MSISRANGE_4M +#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 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @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 internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_MSI +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 1 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 8..127. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 60 +#endif + +/** + * @brief PLLPDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLPDIV_VALUE 0 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 7 +#endif + +/** + * @brief PLLQ divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 4 +#endif + +/** + * @brief PLLR divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLR_VALUE 2 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief STOPWUCK clock setting. + */ +#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) +#define STM32_STOPWUCK STM32_STOPWUCK_MSI +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief LSCO clock source. + */ +#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#endif + +/** + * @brief PLLSAI1M divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSAI1M_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1M_VALUE 1 +#endif + +/** + * @brief PLLSAI1N multiplier value. + * @note The allowed values are 8..127. + */ +#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1N_VALUE 72 +#endif + +/** + * @brief PLLSAI1PDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1PDIV_VALUE 6 +#endif + +/** + * @brief PLLSAI1P divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1P_VALUE 7 +#endif + +/** + * @brief PLLSAI1Q divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1Q_VALUE 6 +#endif + +/** + * @brief PLLSAI1R divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1R_VALUE 6 +#endif + +/** + * @brief PLLSAI2M divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSAI2M_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2M_VALUE 1 +#endif + +/** + * @brief PLLSAI2N multiplier value. + * @note The allowed values are 8..127. + */ +#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2N_VALUE 72 +#endif + +/** + * @brief PLLSAI2PDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2PDIV_VALUE 6 +#endif + +/** + * @brief PLLSAI2P divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2P_VALUE 7 +#endif + +/** + * @brief PLLSAI2Q divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI2Q_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2Q_VALUE 6 +#endif + +/** + * @brief PLLSAI2R divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2R_VALUE 6 +#endif + +/** + * @brief PLLSAI2DIVR value. + */ +#if !defined(STM32_PLLSAI2DIVR) || defined(__DOXYGEN__) +#define STM32_PLLSAI2DIVR STM32_PLLSAI2DIVR_DIV16 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) +#define STM32_UART5SEL STM32_UART5SEL_SYSCLK +#endif + +/** + * @brief LPUART1 clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) +#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK +#endif + +/** + * @brief I2C3 clock source. + */ +#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) +#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK +#endif + +/** + * @brief I2C4 clock source. + */ +#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) +#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#endif + +/** + * @brief LPTIM2 clock source. + */ +#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 +#endif + +/** + * @brief CLK48SEL value (48MHz clock source). + */ +#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) +#define STM32_CLK48SEL STM32_CLK48SEL_PLL +#endif + +/** + * @brief ADCSEL value (ADCs clock source). + */ +#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) +#define STM32_ADCSEL STM32_ADCSEL_SYSCLK +#endif + +/** + * @brief DFSDMSEL value (DFSDM clock source). + */ +#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__) +#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 +#endif + +/** + * @brief ADFSDMSEL value (DFSDM clock source). + */ +#if !defined(STM32_ADFSDMSEL) || defined(__DOXYGEN__) +#define STM32_ADFSDMSEL STM32_ADFSDMSEL_SAI1CLK +#endif + +/** + * @brief SAI1SEL value (SAI1 clock source). + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#endif + +/** + * @brief SAI2SEL value (SAI2 clock source). + */ +#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#endif + +/** + * @brief DSISEL value (DSI clock source). + */ +#if !defined(STM32_DSISEL) || defined(__DOXYGEN__) +#define STM32_DSISEL STM32_DSISEL_DSIPHY +#endif + +/** + * @brief SDMMC value (SDMMC clock source). + */ +#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__) +#define STM32_SDMMCSEL STM32_SDMMCSEL_48CLK +#endif + +/** + * @brief OSPISEL value (OSPISEL clock source). + */ +#if !defined(STM32_OSPISEL) || defined(__DOXYGEN__) +#define STM32_OSPISEL STM32_OSPISEL_SYSCLK +#endif + +/** + * @brief RTC/LCD clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32L4xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4xx_MCUCONF not defined" +#endif + +#if defined(STM32L4R5xx) && !defined(STM32L4R5_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4R5_MCUCONF not defined" + +#elif defined(STM32L4S5xx) && !defined(STM32L4S5_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4S5_MCUCONF not defined" + +#elif defined(STM32L4R7xx) && !defined(STM32L4R7_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4R7_MCUCONF not defined" + +#elif defined(STM32L4S7xx) && !defined(STM32L4S7_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4S7_MCUCONF not defined" + +#elif defined(STM32L4R9xx) && !defined(STM32L4R9_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4R9_MCUCONF not defined" + +#elif defined(STM32L4S9xx) && !defined(STM32L4S9_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4S9_MCUCONF not defined" + +#endif + +/* + * Board files sanity checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif + +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) +/** + * @name System Limits + * @{ + */ +/** + * @brief Maximum SYSCLK clock frequency in boost mode. + */ +#define STM32_SYSCLK_MAX 120000000 + +/** + * @brief Maximum SYSCLK clock frequency in normal mode. + */ +#define STM32_SYSCLK_NOBOOST_MAX 80000000 + +/** + * @brief Maximum HSE clock frequency at current voltage setting. + */ +#define STM32_HSECLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 48000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 8000000 + +/** + * @brief Minimum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MIN 8000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 16000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 2660000 + +/** + * @brief Maximum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MAX 344000000 + +/** + * @brief Minimum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MIN 64000000 + +/** + * @brief Maximum PLL-P output clock frequency. + */ +#define STM32_PLLP_MAX 120000000 + +/** + * @brief Minimum PLL-P output clock frequency. + */ +#define STM32_PLLP_MIN 2064500 + +/** + * @brief Maximum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MAX 120000000 + +/** + * @brief Minimum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MIN 8000000 + +/** + * @brief Maximum PLL-R output clock frequency. + */ +#define STM32_PLLR_MAX 120000000 + +/** + * @brief Minimum PLL-R output clock frequency. + */ +#define STM32_PLLR_MIN 8000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 120000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 120000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 80000000 +/** @} */ + +/** + * @name Flash Wait states + * @{ + */ +#define STM32_0WS_THRESHOLD 20000000 +#define STM32_1WS_THRESHOLD 40000000 +#define STM32_2WS_THRESHOLD 60000000 +#define STM32_3WS_THRESHOLD 80000000 +#define STM32_4WS_THRESHOLD 100000000 +#define STM32_5WS_THRESHOLD 120000000 +/** @} */ + +#elif STM32_VOS == STM32_VOS_RANGE2 +#define STM32_SYSCLK_MAX 26000000 +#define STM32_SYSCLK_NOBOOST_MAX 26000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 26000000 +#define STM32_HSECLK_MIN 8000000 +#define STM32_HSECLK_BYP_MIN 8000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_LSECLK_BYP_MIN 32768 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MIN 2660000 +#define STM32_PLLVCO_MAX 128000000 +#define STM32_PLLVCO_MIN 64000000 +#define STM32_PLLP_MAX 26000000 +#define STM32_PLLP_MIN 2064500 +#define STM32_PLLQ_MAX 26000000 +#define STM32_PLLQ_MIN 8000000 +#define STM32_PLLR_MAX 26000000 +#define STM32_PLLR_MIN 8000000 +#define STM32_PCLK1_MAX 26000000 +#define STM32_PCLK2_MAX 26000000 +#define STM32_ADCCLK_MAX 26000000 + +#define STM32_0WS_THRESHOLD 8000000 +#define STM32_1WS_THRESHOLD 16000000 +#define STM32_2WS_THRESHOLD 26000000 +#define STM32_3WS_THRESHOLD 0 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 + +#else +#error "invalid STM32_VOS value specified" +#endif + +/** + * @brief MSI frequency. + */ +#if STM32_MSIRANGE == STM32_MSIRANGE_100K +#define STM32_MSICLK 100000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_200K +#define STM32_MSICLK 200000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_400K +#define STM32_MSICLK 400000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_800K +#define STM32_MSICLK 800000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_1M +#define STM32_MSICLK 1000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_2M +#define STM32_MSICLK 2000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_4M +#define STM32_MSICLK 4000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_8M +#define STM32_MSICLK 8000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_16M +#define STM32_MSICLK 16000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_24M +#define STM32_MSICLK 24000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_32M +#define STM32_MSICLK 32000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_48M +#define STM32_MSICLK 48000000 +#else +#error "invalid STM32_MSIRANGE value specified" +#endif + +/** + * @brief MSIS frequency. + */ +#if STM32_MSISRANGE == STM32_MSISRANGE_1M +#define STM32_MSISCLK 1000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_2M +#define STM32_MSISCLK 2000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_4M +#define STM32_MSISCLK 4000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_8M +#define STM32_MSISCLK 8000000 +#else +#error "invalid STM32_MSISRANGE value specified" +#endif + +/* + * HSI16 related checks. + */ +#if STM32_HSI16_ENABLED +#else /* !STM32_HSI16_ENABLED */ + +#if STM32_SW == STM32_SW_HSI16 +#error "HSI16 not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +/* NOTE: Missing checks on the HSI16 pre-muxes, it is also required for newer + L4 devices.*/ + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16)) +#error "HSI16 not enabled, required by STM32_MCOSEL" +#endif + +#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SAI1SEL" +#endif + +#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SAI2SEL" +#endif + +#if (STM32_USART1SEL == STM32_USART1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART1SEL" +#endif +#if (STM32_USART2SEL == STM32_USART2SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART2SEL" +#endif +#if (STM32_USART3SEL == STM32_USART3SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART3SEL" +#endif +#if (STM32_UART4SEL == STM32_UART4SEL_HSI16) +#error "HSI16 not enabled, required by STM32_UART4SEL" +#endif +#if (STM32_UART5SEL == STM32_UART5SEL_HSI16) +#error "HSI16 not enabled, required by STM32_UART5SEL" +#endif +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_LPUART1SEL" +#endif + +#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) +#error "HSI16 not enabled, required by I2C1SEL" +#endif +#if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) +#error "HSI16 not enabled, required by I2C2SEL" +#endif +#if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) +#error "HSI16 not enabled, required by I2C3SEL" +#endif +#if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) +#error "HSI16 not enabled, required by I2C4SEL" +#endif + +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) +#error "HSI16 not enabled, required by LPTIM1SEL" +#endif +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) +#error "HSI16 not enabled, required by LPTIM2SEL" +#endif + +#if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16) +#error "HSI16 not enabled, required by STM32_STOPWUCK" +#endif + +#endif /* !STM32_HSI16_ENABLED */ + +#if STM32_HSI48_ENABLED +#else /* !STM32_HSI48_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_HSI48 +#error "HSI48 not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 +#error "HSI48 not enabled, required by STM32_CLK48SEL" +#endif +#endif /* !STM32_HSI48_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + + #if STM32_HSECLK == 0 + #error "HSE frequency not defined" + #else /* STM32_HSECLK != 0 */ + #if defined(STM32_HSE_BYPASS) + #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" + #endif + #else /* !defined(STM32_HSE_BYPASS) */ + #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" + #endif + #endif /* !defined(STM32_HSE_BYPASS) */ + #endif /* STM32_HSECLK != 0 */ + + #else /* !STM32_HSE_ENABLED */ + + #if STM32_SW == STM32_SW_HSE + #error "HSE not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) + #error "HSE not enabled, required by STM32_MCOSEL" + #endif + + #if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) | \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SAI1SEL" + #endif + + #if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) | \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SAI2SEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV + #error "HSE not enabled, required by STM32_RTCSEL" + #endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + + #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) + #error "LSI not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSI + #error "LSI not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSI + #error "LSI not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + + #if (STM32_LSECLK == 0) + #error "LSE frequency not defined" + #endif + + #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) + #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" + #endif + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) + #error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" + #endif + +#else /* !STM32_LSE_ENABLED */ + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) + #error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_LSE + #error "LSE not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSE + #error "LSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSE + #error "LSE not enabled, required by STM32_LSCOSEL" + #endif + + #if STM32_MSIPLL_ENABLED == TRUE + #error "LSE not enabled, required by STM32_MSIPLL_ENABLED" + #endif + +#endif /* !STM32_LSE_ENABLED */ + +/* + * MSI related checks. + */ +#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED +#warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED" +#endif + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) +#else +#error "invalid STM32_PLLM_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_MSI +#define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 +#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK +#define STM32_PLLCLKIN 0 + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLL input frequency range check. + */ +#if (STM32_PLLCLKIN != 0) && \ + ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ + defined(__DOXYGEN__) + +#if STM32_PLLCLKIN == 0 +#error "PLL activation required but no PLL clock selected" +#endif + +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 8) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLP (0 << 17) + +#elif STM32_PLLP_VALUE == 17 +#define STM32_PLLP (1 << 17) + +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLQ (0 << 21) + +#elif STM32_PLLQ_VALUE == 4 +#define STM32_PLLQ (1 << 21) + +#elif STM32_PLLQ_VALUE == 6 +#define STM32_PLLQ (2 << 21) + +#elif STM32_PLLQ_VALUE == 8 +#define STM32_PLLQ (3 << 21) + +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLR field. + */ +#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLR (0 << 25) + +#elif STM32_PLLR_VALUE == 4 +#define STM32_PLLR (1 << 25) + +#elif STM32_PLLR_VALUE == 6 +#define STM32_PLLR (2 << 25) + +#elif STM32_PLLR_VALUE == 8 +#define STM32_PLLR (3 << 25) + +#else +#error "invalid STM32_PLLR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLPDIV field. + */ +#if (STM32_PLLPDIV_VALUE == 0) || \ + ((STM32_PLLPDIV_VALUE != 1) && (STM32_PLLPDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) +#else +#error "invalid STM32_PLLPDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLPEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ + defined(__DOXYGEN__) +#define STM32_PLLPEN (1 << 16) +#else +#define STM32_PLLPEN (0 << 16) +#endif + +/** + * @brief STM32_PLLQEN field. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__) +#define STM32_PLLQEN (1 << 20) +#else +#define STM32_PLLQEN (0 << 20) +#endif + +/** + * @brief STM32_PLLREN field. + */ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + defined(__DOXYGEN__) +#define STM32_PLLREN (1 << 24) +#else +#define STM32_PLLREN (0 << 24) +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL P output clock frequency. + */ +#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) +#else +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) +#endif + +/** + * @brief PLL Q output clock frequency. + */ +#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) + +/** + * @brief PLL R output clock frequency. + */ +#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) + +/* + * PLL-P output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLL-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLL-R output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_MSICLK + +#elif (STM32_SW == STM32_SW_MSI) +#define STM32_SYSCLK STM32_MSICLK + +#elif (STM32_SW == STM32_SW_HSI16) +#define STM32_SYSCLK STM32_HSI16CLK + +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK + +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLL_R_CLKOUT + +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) + +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) + +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) + +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) + +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) + +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) + +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) + +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) + +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) + +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief STM32_PLLSAI1M field. + */ +#if ((STM32_PLLSAI1M_VALUE >= 1) && (STM32_PLLSAI1M_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1M ((STM32_PLLSAI1M_VALUE - 1) << 4) +#else +#error "invalid STM32_PLLSAI1M_VALUE value specified" +#endif + +/** + * @brief PLLSAI1 input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1CLKIN (STM32_HSECLK / STM32_PLLSAI1M_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_MSI +#define STM32_PLLSAI1CLKIN (STM32_MSICLK / STM32_PLLSAI1M_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 +#define STM32_PLLSAI1CLKIN (STM32_HSI16CLK / STM32_PLLSAI1M_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK +#define STM32_PLLSAI1CLKIN 0 + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLLSAI1 input frequency range check. + */ +#if (STM32_PLLSAI1CLKIN != 0) && \ + ((STM32_PLLSAI1CLKIN < STM32_PLLIN_MIN) || \ + (STM32_PLLSAI1CLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLSAI1CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLLSAI1 enable check. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \ + (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ + defined(__DOXYGEN__) + +#if STM32_PLLSAI1CLKIN == 0 +#error "PLLSAI1 activation required but no PLL clock selected" +#endif + +/** + * @brief PLLSAI1 activation flag. + */ +#define STM32_ACTIVATE_PLLSAI1 TRUE +#else +#define STM32_ACTIVATE_PLLSAI1 FALSE +#endif + +/** + * @brief STM32_PLLSAI1N field. + */ +#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 127)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8) +#else +#error "invalid STM32_PLLSAI1N_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1P field. + */ +#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLSAI1P (0 << 17) + +#elif STM32_PLLSAI1P_VALUE == 17 +#define STM32_PLLSAI1P (1 << 17) + +#else +#error "invalid STM32_PLLSAI1P_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1Q field. + */ +#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI1Q (0 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 4 +#define STM32_PLLSAI1Q (1 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 6 +#define STM32_PLLSAI1Q (2 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 8 +#define STM32_PLLSAI1Q (3 << 21) + +#else +#error "invalid STM32_PLLSAI1Q_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1R field. + */ +#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI1R (0 << 25) + +#elif STM32_PLLSAI1R_VALUE == 4 +#define STM32_PLLSAI1R (1 << 25) + +#elif STM32_PLLSAI1R_VALUE == 6 +#define STM32_PLLSAI1R (2 << 25) + +#elif STM32_PLLSAI1R_VALUE == 8 +#define STM32_PLLSAI1R (3 << 25) + +#else +#error "invalid STM32_PLLSAI1R_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1PDIV field. + */ +#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27) +#else +#error "invalid STM32_PLLSAI1PDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1PEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1PEN (1 << 16) +#else +#define STM32_PLLSAI1PEN (0 << 16) +#endif + +/** + * @brief STM32_PLLSAI1QEN field. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_PLLSAI1QEN (1 << 20) +#else +#define STM32_PLLSAI1QEN (0 << 20) +#endif + +/** + * @brief STM32_PLLSAI1REN field. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_PLLSAI1REN (1 << 24) +#else +#define STM32_PLLSAI1REN (0 << 24) +#endif + +/** + * @brief PLLSAI1 VCO frequency. + */ +#define STM32_PLLSAI1VCO (STM32_PLLSAI1CLKIN * STM32_PLLSAI1N_VALUE) + +/* + * PLLSAI1 VCO frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI1-P output clock frequency. + */ +#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE) +#else +#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE) +#endif + +/** + * @brief PLLSAI1-Q output clock frequency. + */ +#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) + +/** + * @brief PLLSAI1-R output clock frequency. + */ +#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE) + +/* + * PLLSAI1-P output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLLSAI1-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLLSAI1-R output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief STM32_PLLSAI2M field. + */ +#if ((STM32_PLLSAI2M_VALUE >= 1) && (STM32_PLLSAI2M_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2M ((STM32_PLLSAI2M_VALUE - 1) << 4) +#else +#error "invalid STM32_PLLSAI2M_VALUE value specified" +#endif + +/** + * @brief PLLSAI2 input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2CLKIN (STM32_HSECLK / STM32_PLLSAI2M_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_MSI +#define STM32_PLLSAI2CLKIN (STM32_MSICLK / STM32_PLLSAI2M_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 +#define STM32_PLLSAI2CLKIN (STM32_HSI16CLK / STM32_PLLSAI2M_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK +#define STM32_PLLSAI2CLKIN 0 + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLLSAI2 input frequency range check. + */ +#if (STM32_PLLSAI2CLKIN != 0) && \ + ((STM32_PLLSAI2CLKIN < STM32_PLLIN_MIN) || \ + (STM32_PLLSAI2CLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLSAI2CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLLSAI2 enable check. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ + defined(__DOXYGEN__) + +#if STM32_PLLSAI2CLKIN == 0 +#error "PLLSAI2 activation required but no PLL clock selected" +#endif + +/** + * @brief PLLSAI2 activation flag. + */ +#define STM32_ACTIVATE_PLLSAI2 TRUE +#else +#define STM32_ACTIVATE_PLLSAI2 FALSE +#endif + +/** + * @brief STM32_PLLSAI2N field. + */ +#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 127)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8) +#else +#error "invalid STM32_PLLSAI2N_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2P field. + */ +#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLSAI2P (0 << 17) + +#elif STM32_PLLSAI2P_VALUE == 17 +#define STM32_PLLSAI2P (1 << 17) + +#else +#error "invalid STM32_PLLSAI2P_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2R field. + */ +#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI2R (0 << 25) + +#elif STM32_PLLSAI2R_VALUE == 4 +#define STM32_PLLSAI2R (1 << 25) + +#elif STM32_PLLSAI2R_VALUE == 6 +#define STM32_PLLSAI2R (2 << 25) + +#elif STM32_PLLSAI2R_VALUE == 8 +#define STM32_PLLSAI2R (3 << 25) + +#else +#error "invalid STM32_PLLSAI2R_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2PDIV field. + */ +#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27) +#else +#error "invalid STM32_PLLSAI2PDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2PEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2PEN (1 << 16) +#else +#define STM32_PLLSAI2PEN (0 << 16) +#endif + +/** + * @brief STM32_PLLSAI2REN field. + * @note Always enabled. + * @note It should depend on some condition. + */ +#define STM32_PLLSAI2REN (1 << 24) + +/** + * @brief PLLSAI2 VCO frequency. + */ +#define STM32_PLLSAI2VCO (STM32_PLLSAI2CLKIN * STM32_PLLSAI2N_VALUE) + +/* + * PLLSAI2 VCO frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI2-P output clock frequency. + */ +#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE) +#else +#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE) +#endif + +/** + * @brief PLLSAI2-R output clock frequency. + */ +#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE) + +/* + * PLLSAI2-P output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLLSAI2-R output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief MCO divider clock frequency. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 + +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK +#define STM32_MCODIVCLK STM32_SYSCLK + +#elif STM32_MCOSEL == STM32_MCOSEL_MSI +#define STM32_MCODIVCLK STM32_MSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 +#define STM32_MCODIVCLK STM32_HSI16CLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_PLL +#define STM32_MCODIVCLK STM32_PLL_R_CLKOUT + +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 +#define STM32_MCODIVCLK STM32_HSI48CLK + +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock frequency. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) + +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief RTC clock frequency. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 clock frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK2 + +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK + +#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 +#define STM32_USART1CLK STM32_HSI16CLK + +#elif STM32_USART1SEL == STM32_USART1SEL_LSE +#define STM32_USART1CLK STM32_LSECLK + +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 clock frequency. + */ +#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART2CLK STM32_PCLK1 + +#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK + +#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 +#define STM32_USART2CLK STM32_HSI16CLK + +#elif STM32_USART2SEL == STM32_USART2SEL_LSE +#define STM32_USART2CLK STM32_LSECLK + +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 clock frequency. + */ +#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART3CLK STM32_PCLK1 + +#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK + +#elif STM32_USART3SEL == STM32_USART3SEL_HSI16 +#define STM32_USART3CLK STM32_HSI16CLK + +#elif STM32_USART3SEL == STM32_USART3SEL_LSE +#define STM32_USART3CLK STM32_LSECLK + +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief UART4 clock frequency. + */ +#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART4CLK STM32_PCLK1 + +#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK +#define STM32_UART4CLK STM32_SYSCLK + +#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 +#define STM32_UART4CLK STM32_HSI16CLK + +#elif STM32_UART4SEL == STM32_UART4SEL_LSE +#define STM32_UART4CLK STM32_LSECLK + +#else +#error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 clock frequency. + */ +#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART5CLK STM32_PCLK1 + +#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK +#define STM32_UART5CLK STM32_SYSCLK + +#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 +#define STM32_UART5CLK STM32_HSI16CLK + +#elif STM32_UART5SEL == STM32_UART5SEL_LSE +#define STM32_UART5CLK STM32_LSECLK + +#else +#error "invalid source selected for UART5 clock" +#endif + +/** + * @brief LPUART1 clock frequency. + */ +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPUART1CLK STM32_PCLK1 + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK +#define STM32_LPUART1CLK STM32_SYSCLK + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 +#define STM32_LPUART1CLK STM32_HSI16CLK + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE +#define STM32_LPUART1CLK STM32_LSECLK + +#else +#error "invalid source selected for LPUART1 clock" +#endif + +/** + * @brief I2C1 clock frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_PCLK1 + +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK + +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 +#define STM32_I2C1CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 clock frequency. + */ +#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C2CLK STM32_PCLK1 + +#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK + +#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 +#define STM32_I2C2CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief I2C3 clock frequency. + */ +#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C3CLK STM32_PCLK1 + +#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK +#define STM32_I2C3CLK STM32_SYSCLK + +#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 +#define STM32_I2C3CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C3 clock" +#endif + +/** + * @brief I2C4 clock frequency. + */ +#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C4CLK STM32_PCLK1 + +#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK +#define STM32_I2C4CLK STM32_SYSCLK + +#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 +#define STM32_I2C4CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C4 clock" +#endif + +/** + * @brief LPTIM1 clock frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM1CLK STM32_PCLK1 + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI +#define STM32_LPTIM1CLK STM32_LSICLK + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 +#define STM32_LPTIM1CLK STM32_HSI16CLK + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE +#define STM32_LPTIM1CLK STM32_LSECLK + +#else +#error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief LPTIM2 clock frequency. + */ +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM2CLK STM32_PCLK1 + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI +#define STM32_LPTIM2CLK STM32_LSICLK + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 +#define STM32_LPTIM2CLK STM32_HSI16CLK + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE +#define STM32_LPTIM2CLK STM32_LSECLK + +#else +#error "invalid source selected for LPTIM2 clock" +#endif + +/** + * @brief 48MHz clock frequency. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) +#define STM32_48CLK STM32_HSI48CLK + +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 +#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) + +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL +#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) + +#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI +#define STM32_48CLK STM32_MSICLK + +#else +#error "invalid source selected for 48CLK clock" +#endif + +/** + * @brief SAI1 clock frequency. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2 +#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL +#define STM32_SAI1CLK STM32_PLL_P_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK +#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ + +#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 +#define STM32_SAI1CLK STM32_HSI16CLK + +#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF +#define STM32_SAI1CLK 0 + +#else +#error "invalid source selected for SAI1 clock" +#endif + +/** + * @brief SAI2 clock frequency. + */ +#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT + +#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2 +#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT + +#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL +#define STM32_SAI2CLK STM32_PLL_P_CLKOUT + +#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK +#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ + +#elif STM32_SAI2SEL == STM32_SAI2SEL_HSI16 +#define STM32_SAI2CLK STM32_HSI16CLK + +#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF +#define STM32_SAI2CLK 0 + +#else +#error "invalid source selected for SAI2 clock" +#endif + +/** + * @brief DSI clock frequency. + */ +#if (STM32_DSISEL == STM32_DSISEL_DSIPHY) || defined(__DOXYGEN__) +#define STM32_DSICLK 0 + +#elif STM32_DSISEL == STM32_DSISEL_PLLDSICLK +#define STM32_DSICLK STM32_PLLSAI2_Q_CLKOUT + +#else +#error "invalid source selected for DSI clock" +#endif + +/** + * @brief SDMMC clock frequency. + */ +#if (STM32_SDMMCSEL == STM32_SDMMCSEL_48CLK) || defined(__DOXYGEN__) +#define STM32_SDMMCCLK STM32_48CLK + +#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLLSAI3CLK +#define STM32_SDMMCCLK STM32_PLL_P_CLKOUT + +#else +#error "invalid source selected for SDMMC clock" +#endif + +/** + * @brief USB clock point. + */ +#define STM32_USBCLK STM32_48CLK + +/** + * @brief RNG clock point. + */ +#define STM32_RNGCLK STM32_48CLK + +/** + * @brief ADC clock frequency. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__) +#define STM32_ADCCLK 0 + +#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1 +#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT + +#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK +#define STM32_ADCCLK STM32_SYSCLK + +#else +#error "invalid source selected for ADC clock" +#endif + +/** + * @brief DFSDM clock frequency. + */ +#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_DFSDMCLK STM32_PCLK2 + +#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK +#define STM32_DFSDMCLK STM32_SYSCLK + +#else +#error "invalid source selected for DFSDM clock" +#endif + +/** + * @brief SDMMC frequency. + */ +#define STM32_SDMMC1CLK STM32_48CLK + +/** + * @brief LTDC frequency. + */ +#if (STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV2) || defined(__DOXYGEN__) +#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 2) + +#elif STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV4 +#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 4) + +#elif STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV8 +#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 8) + +#elif STM32_PLLSAI2DIVR == STM32_PLLSAI2DIVR_DIV16 +#define STM32_LTDCCLK (STM32_PLLSAI2_R_CLKOUT / 16) + +#else +#error "invalid STM32_PLLSAI2DIVR value specified" +#endif + +/** + * @brief OSPI clock frequency. + */ +#if (STM32_OSPISEL == STM32_OSPISEL_SYSCLK) || defined(__DOXYGEN__) +#define STM32_OSPICLK STM32_SYSCLK + +#elif STM32_OSPISEL == STM32_OSPISEL_MSI +#define STM32_OSPICLK STM32_MSICLK + +#elif STM32_OSPISEL == STM32_OSPISEL_48CLK +#define STM32_OSPICLK STM32_PLLSAI1_Q_CLKOUT + +#else +#error "invalid source selected for OSPI clock" +#endif + +/** + * @brief Clock of timers connected to APB1 + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Clock of timers connected to APB2. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Voltage boost settings. + */ +#if (STM32_SYSCLK <= STM32_SYSCLK_NOBOOST_MAX) || defined(__DOXYGEN__) +#define STM32_R1MODE PWR_CR5_R1MODE +#else +#define STM32_R1MODE 0 +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS + +#else +#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS +#endif + +/** + * @brief Flash settings for MSI. + */ +#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_MSICLK <= STM32_1WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_MSICLK <= STM32_2WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_MSICLK <= STM32_3WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS + +#else +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/platform.mk b/os/hal/ports/STM32/STM32L4xx+/platform.mk index 2ad09d7288..9d9e5ae0fe 100644 --- a/os/hal/ports/STM32/STM32L4xx+/platform.mk +++ b/os/hal/ports/STM32/STM32L4xx+/platform.mk @@ -1,49 +1,49 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+/hal_lld.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+/hal_efl_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+ - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+/hal_lld.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+/hal_efl_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx+ + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32L4xx+/stm32_dmamux.h b/os/hal/ports/STM32/STM32L4xx+/stm32_dmamux.h index a7889be365..8b8482127f 100644 --- a/os/hal/ports/STM32/STM32L4xx+/stm32_dmamux.h +++ b/os/hal/ports/STM32/STM32L4xx+/stm32_dmamux.h @@ -1,161 +1,161 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/stm32_dmamux.h - * @brief STM32L4xx+ DMAMUX handler header. - * - * @addtogroup STM32L4xxp_DMAMUX - * @{ - */ - -#ifndef STM32_DMAMUX_H -#define STM32_DMAMUX_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name DMAMUX1 request sources - * @{ - */ -#define STM32_DMAMUX1_REQ_GEN0 1 -#define STM32_DMAMUX1_REQ_GEN1 2 -#define STM32_DMAMUX1_REQ_GEN2 3 -#define STM32_DMAMUX1_REQ_GEN3 4 -#define STM32_DMAMUX1_ADC1 5 -#define STM32_DMAMUX1_DAC1_CH1 6 -#define STM32_DMAMUX1_DAC1_CH2 7 -#define STM32_DMAMUX1_TIM6_UP 8 -#define STM32_DMAMUX1_TIM7_UP 9 -#define STM32_DMAMUX1_SPI1_RX 10 -#define STM32_DMAMUX1_SPI1_TX 11 -#define STM32_DMAMUX1_SPI2_RX 12 -#define STM32_DMAMUX1_SPI2_TX 13 -#define STM32_DMAMUX1_SPI3_RX 14 -#define STM32_DMAMUX1_SPI3_TX 15 -#define STM32_DMAMUX1_I2C1_RX 16 -#define STM32_DMAMUX1_I2C1_TX 17 -#define STM32_DMAMUX1_I2C2_RX 18 -#define STM32_DMAMUX1_I2C2_TX 19 -#define STM32_DMAMUX1_I2C3_RX 20 -#define STM32_DMAMUX1_I2C3_TX 21 -#define STM32_DMAMUX1_I2C4_RX 22 -#define STM32_DMAMUX1_I2C4_TX 23 -#define STM32_DMAMUX1_USART1_RX 24 -#define STM32_DMAMUX1_USART1_TX 25 -#define STM32_DMAMUX1_USART2_RX 26 -#define STM32_DMAMUX1_USART2_TX 27 -#define STM32_DMAMUX1_USART3_RX 28 -#define STM32_DMAMUX1_USART3_TX 29 -#define STM32_DMAMUX1_UART4_RX 30 -#define STM32_DMAMUX1_UART4_TX 31 -#define STM32_DMAMUX1_UART5_RX 32 -#define STM32_DMAMUX1_UART5_TX 33 -#define STM32_DMAMUX1_LPUART1_RX 34 -#define STM32_DMAMUX1_LPUART1_TX 35 -#define STM32_DMAMUX1_SAI1_A 36 -#define STM32_DMAMUX1_SAI1_B 37 -#define STM32_DMAMUX1_SAI2_A 38 -#define STM32_DMAMUX1_SAI2_B 39 -#define STM32_DMAMUX1_OCTOSPI1 40 -#define STM32_DMAMUX1_OCTOSPI2 41 -#define STM32_DMAMUX1_TIM1_CH1 42 -#define STM32_DMAMUX1_TIM1_CH2 43 -#define STM32_DMAMUX1_TIM1_CH3 44 -#define STM32_DMAMUX1_TIM1_CH4 45 -#define STM32_DMAMUX1_TIM1_UP 46 -#define STM32_DMAMUX1_TIM1_TRIG 47 -#define STM32_DMAMUX1_TIM1_COM 48 -#define STM32_DMAMUX1_TIM8_CH1 49 -#define STM32_DMAMUX1_TIM8_CH2 50 -#define STM32_DMAMUX1_TIM8_CH3 51 -#define STM32_DMAMUX1_TIM8_CH4 52 -#define STM32_DMAMUX1_TIM8_UP 53 -#define STM32_DMAMUX1_TIM8_TRIG 54 -#define STM32_DMAMUX1_TIM8_COM 55 -#define STM32_DMAMUX1_TIM2_CH1 56 -#define STM32_DMAMUX1_TIM2_CH2 57 -#define STM32_DMAMUX1_TIM2_CH3 58 -#define STM32_DMAMUX1_TIM2_CH4 59 -#define STM32_DMAMUX1_TIM2_UP 60 -#define STM32_DMAMUX1_TIM3_CH1 61 -#define STM32_DMAMUX1_TIM3_CH2 62 -#define STM32_DMAMUX1_TIM3_CH3 63 -#define STM32_DMAMUX1_TIM3_CH4 64 -#define STM32_DMAMUX1_TIM3_UP 65 -#define STM32_DMAMUX1_TIM3_TRIG 66 -#define STM32_DMAMUX1_TIM4_CH1 67 -#define STM32_DMAMUX1_TIM4_CH2 68 -#define STM32_DMAMUX1_TIM4_CH3 69 -#define STM32_DMAMUX1_TIM4_CH4 70 -#define STM32_DMAMUX1_TIM4_UP 71 -#define STM32_DMAMUX1_TIM5_CH1 72 -#define STM32_DMAMUX1_TIM5_CH2 73 -#define STM32_DMAMUX1_TIM5_CH3 74 -#define STM32_DMAMUX1_TIM5_CH4 75 -#define STM32_DMAMUX1_TIM5_UP 76 -#define STM32_DMAMUX1_TIM5_TRIG 77 -#define STM32_DMAMUX1_TIM15_CH1 78 -#define STM32_DMAMUX1_TIM15_UP 79 -#define STM32_DMAMUX1_TIM15_TRIG 80 -#define STM32_DMAMUX1_TIM15_COM 81 -#define STM32_DMAMUX1_TIM16_CH1 82 -#define STM32_DMAMUX1_TIM16_UP 83 -#define STM32_DMAMUX1_TIM17_CH1 84 -#define STM32_DMAMUX1_TIM17_UP 85 -#define STM32_DMAMUX1_DFSDM1_FLT0 86 -#define STM32_DMAMUX1_DFSDM1_FLT1 87 -#define STM32_DMAMUX1_DFSDM1_FLT2 88 -#define STM32_DMAMUX1_DFSDM1_FLT3 89 -#define STM32_DMAMUX1_DCMI 90 -#define STM32_DMAMUX1_AES_IN 91 -#define STM32_DMAMUX1_AES_OUT 92 -#define STM32_DMAMUX1_HASH_IN 93 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMAMUX_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/stm32_dmamux.h + * @brief STM32L4xx+ DMAMUX handler header. + * + * @addtogroup STM32L4xxp_DMAMUX + * @{ + */ + +#ifndef STM32_DMAMUX_H +#define STM32_DMAMUX_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name DMAMUX1 request sources + * @{ + */ +#define STM32_DMAMUX1_REQ_GEN0 1 +#define STM32_DMAMUX1_REQ_GEN1 2 +#define STM32_DMAMUX1_REQ_GEN2 3 +#define STM32_DMAMUX1_REQ_GEN3 4 +#define STM32_DMAMUX1_ADC1 5 +#define STM32_DMAMUX1_DAC1_CH1 6 +#define STM32_DMAMUX1_DAC1_CH2 7 +#define STM32_DMAMUX1_TIM6_UP 8 +#define STM32_DMAMUX1_TIM7_UP 9 +#define STM32_DMAMUX1_SPI1_RX 10 +#define STM32_DMAMUX1_SPI1_TX 11 +#define STM32_DMAMUX1_SPI2_RX 12 +#define STM32_DMAMUX1_SPI2_TX 13 +#define STM32_DMAMUX1_SPI3_RX 14 +#define STM32_DMAMUX1_SPI3_TX 15 +#define STM32_DMAMUX1_I2C1_RX 16 +#define STM32_DMAMUX1_I2C1_TX 17 +#define STM32_DMAMUX1_I2C2_RX 18 +#define STM32_DMAMUX1_I2C2_TX 19 +#define STM32_DMAMUX1_I2C3_RX 20 +#define STM32_DMAMUX1_I2C3_TX 21 +#define STM32_DMAMUX1_I2C4_RX 22 +#define STM32_DMAMUX1_I2C4_TX 23 +#define STM32_DMAMUX1_USART1_RX 24 +#define STM32_DMAMUX1_USART1_TX 25 +#define STM32_DMAMUX1_USART2_RX 26 +#define STM32_DMAMUX1_USART2_TX 27 +#define STM32_DMAMUX1_USART3_RX 28 +#define STM32_DMAMUX1_USART3_TX 29 +#define STM32_DMAMUX1_UART4_RX 30 +#define STM32_DMAMUX1_UART4_TX 31 +#define STM32_DMAMUX1_UART5_RX 32 +#define STM32_DMAMUX1_UART5_TX 33 +#define STM32_DMAMUX1_LPUART1_RX 34 +#define STM32_DMAMUX1_LPUART1_TX 35 +#define STM32_DMAMUX1_SAI1_A 36 +#define STM32_DMAMUX1_SAI1_B 37 +#define STM32_DMAMUX1_SAI2_A 38 +#define STM32_DMAMUX1_SAI2_B 39 +#define STM32_DMAMUX1_OCTOSPI1 40 +#define STM32_DMAMUX1_OCTOSPI2 41 +#define STM32_DMAMUX1_TIM1_CH1 42 +#define STM32_DMAMUX1_TIM1_CH2 43 +#define STM32_DMAMUX1_TIM1_CH3 44 +#define STM32_DMAMUX1_TIM1_CH4 45 +#define STM32_DMAMUX1_TIM1_UP 46 +#define STM32_DMAMUX1_TIM1_TRIG 47 +#define STM32_DMAMUX1_TIM1_COM 48 +#define STM32_DMAMUX1_TIM8_CH1 49 +#define STM32_DMAMUX1_TIM8_CH2 50 +#define STM32_DMAMUX1_TIM8_CH3 51 +#define STM32_DMAMUX1_TIM8_CH4 52 +#define STM32_DMAMUX1_TIM8_UP 53 +#define STM32_DMAMUX1_TIM8_TRIG 54 +#define STM32_DMAMUX1_TIM8_COM 55 +#define STM32_DMAMUX1_TIM2_CH1 56 +#define STM32_DMAMUX1_TIM2_CH2 57 +#define STM32_DMAMUX1_TIM2_CH3 58 +#define STM32_DMAMUX1_TIM2_CH4 59 +#define STM32_DMAMUX1_TIM2_UP 60 +#define STM32_DMAMUX1_TIM3_CH1 61 +#define STM32_DMAMUX1_TIM3_CH2 62 +#define STM32_DMAMUX1_TIM3_CH3 63 +#define STM32_DMAMUX1_TIM3_CH4 64 +#define STM32_DMAMUX1_TIM3_UP 65 +#define STM32_DMAMUX1_TIM3_TRIG 66 +#define STM32_DMAMUX1_TIM4_CH1 67 +#define STM32_DMAMUX1_TIM4_CH2 68 +#define STM32_DMAMUX1_TIM4_CH3 69 +#define STM32_DMAMUX1_TIM4_CH4 70 +#define STM32_DMAMUX1_TIM4_UP 71 +#define STM32_DMAMUX1_TIM5_CH1 72 +#define STM32_DMAMUX1_TIM5_CH2 73 +#define STM32_DMAMUX1_TIM5_CH3 74 +#define STM32_DMAMUX1_TIM5_CH4 75 +#define STM32_DMAMUX1_TIM5_UP 76 +#define STM32_DMAMUX1_TIM5_TRIG 77 +#define STM32_DMAMUX1_TIM15_CH1 78 +#define STM32_DMAMUX1_TIM15_UP 79 +#define STM32_DMAMUX1_TIM15_TRIG 80 +#define STM32_DMAMUX1_TIM15_COM 81 +#define STM32_DMAMUX1_TIM16_CH1 82 +#define STM32_DMAMUX1_TIM16_UP 83 +#define STM32_DMAMUX1_TIM17_CH1 84 +#define STM32_DMAMUX1_TIM17_UP 85 +#define STM32_DMAMUX1_DFSDM1_FLT0 86 +#define STM32_DMAMUX1_DFSDM1_FLT1 87 +#define STM32_DMAMUX1_DFSDM1_FLT2 88 +#define STM32_DMAMUX1_DFSDM1_FLT3 89 +#define STM32_DMAMUX1_DCMI 90 +#define STM32_DMAMUX1_AES_IN 91 +#define STM32_DMAMUX1_AES_OUT 92 +#define STM32_DMAMUX1_HASH_IN 93 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMAMUX_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/stm32_isr.c b/os/hal/ports/STM32/STM32L4xx+/stm32_isr.c index e36ca8db0e..8423676183 100644 --- a/os/hal/ports/STM32/STM32L4xx+/stm32_isr.c +++ b/os/hal/ports/STM32/STM32L4xx+/stm32_isr.c @@ -1,165 +1,165 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/stm32_isr.c - * @brief STM32L4xx+ ISR handler code. - * - * @addtogroup STM32L4xxp_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_exti0.inc" -#include "stm32_exti1.inc" -#include "stm32_exti2.inc" -#include "stm32_exti3.inc" -#include "stm32_exti4.inc" -#include "stm32_exti5_9.inc" -#include "stm32_exti10_15.inc" -#include "stm32_exti16-35_38.inc" -#include "stm32_exti18.inc" -#include "stm32_exti19.inc" -#include "stm32_exti20.inc" -#include "stm32_exti21_22.inc" - -#include "stm32_sdmmc1.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart3.inc" -#include "stm32_uart4.inc" -#include "stm32_uart5.inc" -#include "stm32_lpuart1.inc" - -#include "stm32_tim1_15_16_17.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim4.inc" -#include "stm32_tim5.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim8.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_irq_init(); - exti1_irq_init(); - exti2_irq_init(); - exti3_irq_init(); - exti4_irq_init(); - exti5_9_irq_init(); - exti10_15_irq_init(); - exti16_exti35_38_irq_init(); - exti18_irq_init(); - exti19_irq_init(); - exti21_22_irq_init(); - - sdmmc1_irq_init(); - - tim1_tim15_tim16_tim17_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim4_irq_init(); - tim5_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim8_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_irq_init(); - uart4_irq_init(); - uart5_irq_init(); - lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_irq_deinit(); - exti1_irq_deinit(); - exti2_irq_deinit(); - exti3_irq_deinit(); - exti4_irq_deinit(); - exti5_9_irq_deinit(); - exti10_15_irq_deinit(); - exti16_exti35_38_irq_deinit(); - exti18_irq_deinit(); - exti19_irq_deinit(); - exti21_22_irq_deinit(); - - sdmmc1_irq_deinit(); - - tim1_tim15_tim16_tim17_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim4_irq_deinit(); - tim5_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim8_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_irq_deinit(); - uart4_irq_deinit(); - uart5_irq_deinit(); - lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/stm32_isr.c + * @brief STM32L4xx+ ISR handler code. + * + * @addtogroup STM32L4xxp_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_exti0.inc" +#include "stm32_exti1.inc" +#include "stm32_exti2.inc" +#include "stm32_exti3.inc" +#include "stm32_exti4.inc" +#include "stm32_exti5_9.inc" +#include "stm32_exti10_15.inc" +#include "stm32_exti16-35_38.inc" +#include "stm32_exti18.inc" +#include "stm32_exti19.inc" +#include "stm32_exti20.inc" +#include "stm32_exti21_22.inc" + +#include "stm32_sdmmc1.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart3.inc" +#include "stm32_uart4.inc" +#include "stm32_uart5.inc" +#include "stm32_lpuart1.inc" + +#include "stm32_tim1_15_16_17.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim4.inc" +#include "stm32_tim5.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim8.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_irq_init(); + exti1_irq_init(); + exti2_irq_init(); + exti3_irq_init(); + exti4_irq_init(); + exti5_9_irq_init(); + exti10_15_irq_init(); + exti16_exti35_38_irq_init(); + exti18_irq_init(); + exti19_irq_init(); + exti21_22_irq_init(); + + sdmmc1_irq_init(); + + tim1_tim15_tim16_tim17_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim4_irq_init(); + tim5_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim8_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_irq_init(); + uart4_irq_init(); + uart5_irq_init(); + lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_irq_deinit(); + exti1_irq_deinit(); + exti2_irq_deinit(); + exti3_irq_deinit(); + exti4_irq_deinit(); + exti5_9_irq_deinit(); + exti10_15_irq_deinit(); + exti16_exti35_38_irq_deinit(); + exti18_irq_deinit(); + exti19_irq_deinit(); + exti21_22_irq_deinit(); + + sdmmc1_irq_deinit(); + + tim1_tim15_tim16_tim17_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim4_irq_deinit(); + tim5_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim8_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_irq_deinit(); + uart4_irq_deinit(); + uart5_irq_deinit(); + lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/stm32_isr.h b/os/hal/ports/STM32/STM32L4xx+/stm32_isr.h index 9e25c86891..cfc357e559 100644 --- a/os/hal/ports/STM32/STM32L4xx+/stm32_isr.h +++ b/os/hal/ports/STM32/STM32L4xx+/stm32_isr.h @@ -1,290 +1,290 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/stm32_isr.h - * @brief STM32L4xx+ ISR handler header. - * - * @addtogroup STM32L4xxp_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM8_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC unit. - */ -#define STM32_ADC1_HANDLER Vector88 - -#define STM32_ADC1_NUMBER 18 - -/* - * CAN unit. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 - -/* - * DMA unit. - */ -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH6_HANDLER Vector150 -#define STM32_DMA2_CH7_HANDLER Vector154 - -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 -#define STM32_DMA2_CH6_NUMBER 68 -#define STM32_DMA2_CH7_NUMBER 69 - -/* - * EXTI unit. - */ -#define STM32_EXTI0_HANDLER Vector58 -#define STM32_EXTI1_HANDLER Vector5C -#define STM32_EXTI2_HANDLER Vector60 -#define STM32_EXTI3_HANDLER Vector64 -#define STM32_EXTI4_HANDLER Vector68 -#define STM32_EXTI5_9_HANDLER Vector9C -#define STM32_EXTI10_15_HANDLER VectorE0 -#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1 PVM4 */ -#define STM32_EXTI18_HANDLER VectorE4 /* RTC ALARM */ -#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */ -#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */ -#define STM32_EXTI21_22_HANDLER Vector140 /* COMP1..2 */ - -#define STM32_EXTI0_NUMBER 6 -#define STM32_EXTI1_NUMBER 7 -#define STM32_EXTI2_NUMBER 8 -#define STM32_EXTI3_NUMBER 9 -#define STM32_EXTI4_NUMBER 10 -#define STM32_EXTI5_9_NUMBER 23 -#define STM32_EXTI10_15_NUMBER 40 -#define STM32_EXTI1635_38_NUMBER 1 -#define STM32_EXTI18_NUMBER 41 -#define STM32_EXTI19_NUMBER 2 -#define STM32_EXTI20_NUMBER 3 -#define STM32_EXTI21_22_NUMBER 64 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C3_EVENT_HANDLER Vector160 -#define STM32_I2C3_ERROR_HANDLER Vector164 -#define STM32_I2C4_ERROR_HANDLER Vector18C -#define STM32_I2C4_EVENT_HANDLER Vector190 - -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 -#define STM32_I2C3_EVENT_NUMBER 72 -#define STM32_I2C3_ERROR_NUMBER 73 -#define STM32_I2C4_ERROR_NUMBER 83 -#define STM32_I2C4_EVENT_NUMBER 84 - - -/* - * OCTOSPI unit. - */ -#define STM32_OCTOSPI1_HANDLER Vector15C -#define STM32_OCTOSPI2_HANDLER Vector170 - -#define STM32_OCTOSPI1_NUMBER 71 -#define STM32_OCTOSPI2_NUMBER 76 - -/* - * SDMMC unit. - */ -#define STM32_SDMMC1_HANDLER Vector104 - -#define STM32_SDMMC1_NUMBER 49 - -/* - * TIM units. - */ -#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0 -#define STM32_TIM1_UP_TIM16_HANDLER VectorA4 -#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_BRK_HANDLER VectorEC -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_TRGCO_HANDLER VectorF4 -#define STM32_TIM8_CC_HANDLER VectorF8 - -#define STM32_TIM1_BRK_TIM15_NUMBER 24 -#define STM32_TIM1_UP_TIM16_NUMBER 25 -#define STM32_TIM1_TRGCO_TIM17_NUMBER 26 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_BRK_NUMBER 43 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_TRGCO_NUMBER 45 -#define STM32_TIM8_CC_NUMBER 46 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_LPUART1_HANDLER Vector158 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_LPUART1_NUMBER 70 - -/* - * USB/OTG units. - */ -#define STM32_OTG1_HANDLER Vector14C - -#define STM32_OTG1_NUMBER 67 - -/* - * DMA2D unit. - */ -#define STM32_DMA2D_HANDLER Vector1A8 - -#define STM32_DMA2D_NUMBER 90 - -/* - * FSMC unit. - */ -#define STM32_FSMC_HANDLER Vector100 - -#define STM32_FSMC_NUMBER 48 - -/* - * DCMI unit. - */ -#define STM32_DCMI_HANDLER Vector14C - -#define STM32_DCMI_NUMBER 85 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/stm32_isr.h + * @brief STM32L4xx+ ISR handler header. + * + * @addtogroup STM32L4xxp_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM8_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC unit. + */ +#define STM32_ADC1_HANDLER Vector88 + +#define STM32_ADC1_NUMBER 18 + +/* + * CAN unit. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 + +/* + * DMA unit. + */ +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH6_HANDLER Vector150 +#define STM32_DMA2_CH7_HANDLER Vector154 + +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 +#define STM32_DMA2_CH6_NUMBER 68 +#define STM32_DMA2_CH7_NUMBER 69 + +/* + * EXTI unit. + */ +#define STM32_EXTI0_HANDLER Vector58 +#define STM32_EXTI1_HANDLER Vector5C +#define STM32_EXTI2_HANDLER Vector60 +#define STM32_EXTI3_HANDLER Vector64 +#define STM32_EXTI4_HANDLER Vector68 +#define STM32_EXTI5_9_HANDLER Vector9C +#define STM32_EXTI10_15_HANDLER VectorE0 +#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1 PVM4 */ +#define STM32_EXTI18_HANDLER VectorE4 /* RTC ALARM */ +#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */ +#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */ +#define STM32_EXTI21_22_HANDLER Vector140 /* COMP1..2 */ + +#define STM32_EXTI0_NUMBER 6 +#define STM32_EXTI1_NUMBER 7 +#define STM32_EXTI2_NUMBER 8 +#define STM32_EXTI3_NUMBER 9 +#define STM32_EXTI4_NUMBER 10 +#define STM32_EXTI5_9_NUMBER 23 +#define STM32_EXTI10_15_NUMBER 40 +#define STM32_EXTI1635_38_NUMBER 1 +#define STM32_EXTI18_NUMBER 41 +#define STM32_EXTI19_NUMBER 2 +#define STM32_EXTI20_NUMBER 3 +#define STM32_EXTI21_22_NUMBER 64 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C3_EVENT_HANDLER Vector160 +#define STM32_I2C3_ERROR_HANDLER Vector164 +#define STM32_I2C4_ERROR_HANDLER Vector18C +#define STM32_I2C4_EVENT_HANDLER Vector190 + +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 +#define STM32_I2C3_EVENT_NUMBER 72 +#define STM32_I2C3_ERROR_NUMBER 73 +#define STM32_I2C4_ERROR_NUMBER 83 +#define STM32_I2C4_EVENT_NUMBER 84 + + +/* + * OCTOSPI unit. + */ +#define STM32_OCTOSPI1_HANDLER Vector15C +#define STM32_OCTOSPI2_HANDLER Vector170 + +#define STM32_OCTOSPI1_NUMBER 71 +#define STM32_OCTOSPI2_NUMBER 76 + +/* + * SDMMC unit. + */ +#define STM32_SDMMC1_HANDLER Vector104 + +#define STM32_SDMMC1_NUMBER 49 + +/* + * TIM units. + */ +#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0 +#define STM32_TIM1_UP_TIM16_HANDLER VectorA4 +#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_BRK_HANDLER VectorEC +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_TRGCO_HANDLER VectorF4 +#define STM32_TIM8_CC_HANDLER VectorF8 + +#define STM32_TIM1_BRK_TIM15_NUMBER 24 +#define STM32_TIM1_UP_TIM16_NUMBER 25 +#define STM32_TIM1_TRGCO_TIM17_NUMBER 26 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_BRK_NUMBER 43 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_TRGCO_NUMBER 45 +#define STM32_TIM8_CC_NUMBER 46 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_LPUART1_HANDLER Vector158 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_LPUART1_NUMBER 70 + +/* + * USB/OTG units. + */ +#define STM32_OTG1_HANDLER Vector14C + +#define STM32_OTG1_NUMBER 67 + +/* + * DMA2D unit. + */ +#define STM32_DMA2D_HANDLER Vector1A8 + +#define STM32_DMA2D_NUMBER 90 + +/* + * FSMC unit. + */ +#define STM32_FSMC_HANDLER Vector100 + +#define STM32_FSMC_NUMBER 48 + +/* + * DCMI unit. + */ +#define STM32_DCMI_HANDLER Vector14C + +#define STM32_DCMI_NUMBER 85 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/stm32_rcc.h b/os/hal/ports/STM32/STM32L4xx+/stm32_rcc.h index a7c238aa65..92b38f3f1d 100644 --- a/os/hal/ports/STM32/STM32L4xx+/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32L4xx+/stm32_rcc.h @@ -1,1358 +1,1358 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32l4xx.h. - * - * @addtogroup STM32L4xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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 (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R1(mask, lp) { \ - RCC->APB1ENR1 |= (mask); \ - if (lp) \ - RCC->APB1SMENR1 |= (mask); \ - else \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccDisableAPB1R1(mask) { \ - RCC->APB1ENR1 &= ~(mask); \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccResetAPB1R1(mask) { \ - RCC->APB1RSTR1 |= (mask); \ - RCC->APB1RSTR1 &= ~(mask); \ - (void)RCC->APB1RSTR1; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R2(mask, lp) { \ - RCC->APB1ENR2 |= (mask); \ - if (lp) \ - RCC->APB1SMENR2 |= (mask); \ - else \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccDisableAPB1R2(mask) { \ - RCC->APB1ENR2 &= ~(mask); \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccResetAPB1R2(mask) { \ - RCC->APB1RSTR2 |= (mask); \ - RCC->APB1RSTR2 &= ~(mask); \ - (void)RCC->APB1RSTR2; \ -} - -/** - * @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->APB2SMENR |= (mask); \ - else \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @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->AHB1SMENR |= (mask); \ - else \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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->AHB2SMENR |= (mask); \ - else \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @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->AHB3SMENR |= (mask); \ - else \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2/ADC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC123(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp) - -/** - * @brief Disables the ADC1/ADC2/ADC3 peripheral clock. - * - * @api - */ -#define rccDisableADC123() rccDisableAHB2(RCC_AHB2ENR_ADCEN) - -/** - * @brief Resets the ADC1/ADC2/ADC3 peripheral. - * - * @api - */ -#define rccResetADC123() rccResetAHB2(RCC_AHB2RSTR_ADCRST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name DMAMUX peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMAMUX peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp) - -/** - * @brief Disables the DMAMUX peripheral clock. - * - * @api - */ -#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN) - -/** - * @brief Resets the DMAMUX peripheral. - * - * @api - */ -#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1R1(RCC_APB1ENR1_CAN1EN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1R1(RCC_APB1RSTR1_CAN1RST) - -/** - * @brief Enables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN2(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN2EN, lp) - -/** - * @brief Disables the CAN2 peripheral clock. - * - * @api - */ -#define rccDisableCAN2() rccDisableAPB1R1(RCC_APB1ENR1_CAN2EN) - -/** - * @brief Resets the CAN2 peripheral. - * - * @api - */ -#define rccResetCAN2() rccResetAPB1R1(RCC_APB1RSTR1_CAN2RST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) - -/** - * @brief Enables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) - -/** - * @brief Disables the I2C3 peripheral clock. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @api - */ -#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) - -/** - * @brief Disables the OTG_FS peripheral clock. - * - * @api - */ -#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) - -/** - * @brief Resets the OTG_FS peripheral. - * - * @api - */ -#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) -/** @} */ - -/** - * @name OCTOSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OCTOSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOCTOSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_OSPI1EN, lp) - -/** - * @brief Disables the OCTOSPI1 peripheral clock. - * - * @api - */ -#define rccDisableOCTOSPI1() rccDisableAHB3(RCC_AHB3ENR_OSPI1EN) - -/** - * @brief Resets the OCTOSPI1 peripheral. - * - * @api - */ -#define rccResetOCTOSPI1() rccResetAHB3(RCC_AHB3RSTR_OSPI1RST) - -/** - * @brief Enables the OCTOSPI2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOCTOSPI2(lp) rccEnableAHB3(RCC_AHB3ENR_OSPI2EN, lp) - -/** - * @brief Disables the OCTOSPI2 peripheral clock. - * - * @api - */ -#define rccDisableOCTOSPI2() rccDisableAHB3(RCC_AHB3ENR_OSPI2EN) - -/** - * @brief Resets the OCTOSPI1 peripheral. - * - * @api - */ -#define rccResetOCTOSPI2() rccResetAHB3(RCC_AHB3RSTR_OSPI2RST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) -/** @} */ - -/** - * @name SDMMC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDMMC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC1(lp) rccEnableAHB2(RCC_AHB2ENR_SDMMC1EN, lp) - -/** - * @brief Disables the SDMMC1 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC1() rccDisableAHB2(RCC_AHB2ENR_SDMMC1EN) - -/** - * @brief Resets the SDMMC1 peripheral. - * - * @api - */ -#define rccResetSDMMC1() rccResetAHB2(RCC_AHB2RSTR_SDMMC1RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) - -/** - * @brief Resets the FSMC peripheral. - * - * @api - */ -#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) -/** @} */ - -/** - * @name DCMI peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DCMI peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDCMI(lp) rccEnableAHB2(RCC_AHB2ENR_DCMIEN, lp) - -/** - * @brief Disables the DCMI peripheral clock. -+ * -+ * @api - */ -#define rccDisableDCMI() rccDisableAHB2(RCC_AHB2ENR_DCMIEN) - -/** - * @brief Resets the DCMI peripheral. - * - * @api - */ -#define rccResetDCMI() rccResetAHB2(RCC_AHB2RSTR_DCMIRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32l4xx.h. + * + * @addtogroup STM32L4xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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 (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R1(mask, lp) { \ + RCC->APB1ENR1 |= (mask); \ + if (lp) \ + RCC->APB1SMENR1 |= (mask); \ + else \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccDisableAPB1R1(mask) { \ + RCC->APB1ENR1 &= ~(mask); \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccResetAPB1R1(mask) { \ + RCC->APB1RSTR1 |= (mask); \ + RCC->APB1RSTR1 &= ~(mask); \ + (void)RCC->APB1RSTR1; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R2(mask, lp) { \ + RCC->APB1ENR2 |= (mask); \ + if (lp) \ + RCC->APB1SMENR2 |= (mask); \ + else \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccDisableAPB1R2(mask) { \ + RCC->APB1ENR2 &= ~(mask); \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccResetAPB1R2(mask) { \ + RCC->APB1RSTR2 |= (mask); \ + RCC->APB1RSTR2 &= ~(mask); \ + (void)RCC->APB1RSTR2; \ +} + +/** + * @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->APB2SMENR |= (mask); \ + else \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @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->AHB1SMENR |= (mask); \ + else \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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->AHB2SMENR |= (mask); \ + else \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @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->AHB3SMENR |= (mask); \ + else \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2/ADC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC123(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp) + +/** + * @brief Disables the ADC1/ADC2/ADC3 peripheral clock. + * + * @api + */ +#define rccDisableADC123() rccDisableAHB2(RCC_AHB2ENR_ADCEN) + +/** + * @brief Resets the ADC1/ADC2/ADC3 peripheral. + * + * @api + */ +#define rccResetADC123() rccResetAHB2(RCC_AHB2RSTR_ADCRST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name DMAMUX peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMAMUX peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp) + +/** + * @brief Disables the DMAMUX peripheral clock. + * + * @api + */ +#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN) + +/** + * @brief Resets the DMAMUX peripheral. + * + * @api + */ +#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1R1(RCC_APB1ENR1_CAN1EN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1R1(RCC_APB1RSTR1_CAN1RST) + +/** + * @brief Enables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN2(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN2EN, lp) + +/** + * @brief Disables the CAN2 peripheral clock. + * + * @api + */ +#define rccDisableCAN2() rccDisableAPB1R1(RCC_APB1ENR1_CAN2EN) + +/** + * @brief Resets the CAN2 peripheral. + * + * @api + */ +#define rccResetCAN2() rccResetAPB1R1(RCC_APB1RSTR1_CAN2RST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) + +/** + * @brief Enables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) + +/** + * @brief Disables the I2C3 peripheral clock. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @api + */ +#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) + +/** + * @brief Disables the OTG_FS peripheral clock. + * + * @api + */ +#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) + +/** + * @brief Resets the OTG_FS peripheral. + * + * @api + */ +#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) +/** @} */ + +/** + * @name OCTOSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OCTOSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOCTOSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_OSPI1EN, lp) + +/** + * @brief Disables the OCTOSPI1 peripheral clock. + * + * @api + */ +#define rccDisableOCTOSPI1() rccDisableAHB3(RCC_AHB3ENR_OSPI1EN) + +/** + * @brief Resets the OCTOSPI1 peripheral. + * + * @api + */ +#define rccResetOCTOSPI1() rccResetAHB3(RCC_AHB3RSTR_OSPI1RST) + +/** + * @brief Enables the OCTOSPI2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOCTOSPI2(lp) rccEnableAHB3(RCC_AHB3ENR_OSPI2EN, lp) + +/** + * @brief Disables the OCTOSPI2 peripheral clock. + * + * @api + */ +#define rccDisableOCTOSPI2() rccDisableAHB3(RCC_AHB3ENR_OSPI2EN) + +/** + * @brief Resets the OCTOSPI1 peripheral. + * + * @api + */ +#define rccResetOCTOSPI2() rccResetAHB3(RCC_AHB3RSTR_OSPI2RST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) +/** @} */ + +/** + * @name SDMMC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDMMC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC1(lp) rccEnableAHB2(RCC_AHB2ENR_SDMMC1EN, lp) + +/** + * @brief Disables the SDMMC1 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC1() rccDisableAHB2(RCC_AHB2ENR_SDMMC1EN) + +/** + * @brief Resets the SDMMC1 peripheral. + * + * @api + */ +#define rccResetSDMMC1() rccResetAHB2(RCC_AHB2RSTR_SDMMC1RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) + +/** + * @brief Resets the FSMC peripheral. + * + * @api + */ +#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) +/** @} */ + +/** + * @name DCMI peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DCMI peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDCMI(lp) rccEnableAHB2(RCC_AHB2ENR_DCMIEN, lp) + +/** + * @brief Disables the DCMI peripheral clock. ++ * ++ * @api + */ +#define rccDisableDCMI() rccDisableAHB2(RCC_AHB2ENR_DCMIEN) + +/** + * @brief Resets the DCMI peripheral. + * + * @api + */ +#define rccResetDCMI() rccResetAHB2(RCC_AHB2RSTR_DCMIRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h b/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h index 88673699c7..124f335173 100644 --- a/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h @@ -1,282 +1,282 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx+/stm32_registry.h - * @brief STM32L4xx+ capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32L4xx+ capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 128 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 18 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ -} while (false) - -#if defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \ - defined(__DOXYGEN__) -#define STM32_HAS_HASH1 TRUE -#define STM32_HAS_CRYP1 TRUE -#else -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE -#endif - -/* I2C attributes.*/ -#define STM32_I2C4_USE_BDMA FALSE - -/*===========================================================================*/ -/* STM32L4yyxx+. */ -/*===========================================================================*/ - -#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || \ - defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \ - defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 14 -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 7 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 41 -#define STM32_EXTI_IMR1_MASK 0xFF820000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOFEN | \ - RCC_AHB2ENR_GPIOGEN | \ - RCC_AHB2ENR_GPIOHEN | \ - RCC_AHB2ENR_GPIOIEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 TRUE -#define STM32_HAS_I2C4 TRUE - -/* OCTOSPI attributes.*/ -#define STM32_HAS_OCTOSPI1 TRUE -#define STM32_HAS_OCTOSPI2 TRUE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 2 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_UART5 TRUE -#define STM32_HAS_LPUART1 TRUE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC TRUE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI TRUE - -#endif /* defined(STM32L4R5xx) || defined(STM32L4R7xx) || - defined(STM32L4R9xx) || defined(STM32L4S5xx) || - defined(STM32L4S7xx) || defined(STM32L4S9xx) */ - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx+/stm32_registry.h + * @brief STM32L4xx+ capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32L4xx+ capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 18 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ +} while (false) + +#if defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \ + defined(__DOXYGEN__) +#define STM32_HAS_HASH1 TRUE +#define STM32_HAS_CRYP1 TRUE +#else +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE +#endif + +/* I2C attributes.*/ +#define STM32_I2C4_USE_BDMA FALSE + +/*===========================================================================*/ +/* STM32L4yyxx+. */ +/*===========================================================================*/ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || \ + defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \ + defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 14 +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 7 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 41 +#define STM32_EXTI_IMR1_MASK 0xFF820000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOFEN | \ + RCC_AHB2ENR_GPIOGEN | \ + RCC_AHB2ENR_GPIOHEN | \ + RCC_AHB2ENR_GPIOIEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 TRUE +#define STM32_HAS_I2C4 TRUE + +/* OCTOSPI attributes.*/ +#define STM32_HAS_OCTOSPI1 TRUE +#define STM32_HAS_OCTOSPI2 TRUE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 2 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_UART5 TRUE +#define STM32_HAS_LPUART1 TRUE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC TRUE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI TRUE + +#endif /* defined(STM32L4R5xx) || defined(STM32L4R7xx) || + defined(STM32L4R9xx) || defined(STM32L4S5xx) || + defined(STM32L4S7xx) || defined(STM32L4S9xx) */ + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c b/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c index 6ea46f8b14..7c534e7629 100644 --- a/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c +++ b/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c @@ -1,542 +1,542 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_efl_lld.c - * @brief STM32L4xx Embedded Flash subsystem low level driver source. - * - * @addtogroup HAL_EFL - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define STM32_FLASH_SECTOR_SIZE 2048U -#define STM32_FLASH_LINE_SIZE 8U -#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U) - -#define FLASH_PDKEY1 0x04152637U -#define FLASH_PDKEY2 0xFAFBFCFDU - -#define FLASH_KEY1 0x45670123U -#define FLASH_KEY2 0xCDEF89ABU - -#define FLASH_OPTKEY1 0x08192A3BU -#define FLASH_OPTKEY2 0x4C5D6E7FU - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief EFL1 driver identifier. - */ -EFlashDriver EFLD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const flash_descriptor_t efl_lld_descriptor = { - .attributes = FLASH_ATTR_ERASED_IS_ONE | - FLASH_ATTR_MEMORY_MAPPED | - FLASH_ATTR_ECC_CAPABLE | - FLASH_ATTR_ECC_ZERO_LINE_CAPABLE, - .page_size = STM32_FLASH_LINE_SIZE, - .sectors_count = STM32_FLASH_NUMBER_OF_BANKS * - STM32_FLASH_SECTORS_PER_BANK, - .sectors = NULL, - .sectors_size = STM32_FLASH_SECTOR_SIZE, - .address = (uint8_t *)0x08000000U, - .size = STM32_FLASH_NUMBER_OF_BANKS * - STM32_FLASH_SECTORS_PER_BANK * - STM32_FLASH_SECTOR_SIZE -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static inline void stm32_flash_lock(EFlashDriver *eflp) { - - eflp->flash->CR |= FLASH_CR_LOCK; -} - -static inline void stm32_flash_unlock(EFlashDriver *eflp) { - - eflp->flash->KEYR |= FLASH_KEY1; - eflp->flash->KEYR |= FLASH_KEY2; -} - -static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) { - - eflp->flash->CR |= FLASH_CR_PG; -} - -static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) { - - eflp->flash->CR &= ~FLASH_CR_PG; -} - -static inline void stm32_flash_clear_status(EFlashDriver *eflp) { - - eflp->flash->SR = 0x0000FFFFU; -} - -static inline void stm32_flash_wait_busy(EFlashDriver *eflp) { - - /* Wait for busy bit clear.*/ - while ((eflp->flash->SR & FLASH_SR_BSY) != 0U) { - } -} - -static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) { - uint32_t sr = eflp->flash->SR; - - /* Clearing error conditions.*/ - eflp->flash->SR = sr & 0x0000FFFFU; - - /* Some errors are only caught by assertion.*/ - osalDbgAssert((sr & (FLASH_SR_FASTERR | - FLASH_SR_MISERR | - FLASH_SR_SIZERR)) == 0U, "unexpected flash error"); - - /* Decoding relevant errors.*/ - if ((sr & FLASH_SR_WRPERR) != 0U) { - return FLASH_ERROR_HW_FAILURE; - } - - if ((sr & (FLASH_SR_PGAERR | FLASH_SR_PROGERR | FLASH_SR_OPERR)) != 0U) { - return eflp->state == FLASH_PGM ? FLASH_ERROR_PROGRAM : FLASH_ERROR_ERASE; - } - - return FLASH_NO_ERROR; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level Embedded Flash driver initialization. - * - * @notapi - */ -void efl_lld_init(void) { - - /* Driver initialization.*/ - eflObjectInit(&EFLD1); - EFLD1.flash = FLASH; -} - -/** - * @brief Configures and activates the Embedded Flash peripheral. - * - * @param[in] eflp pointer to a @p EFlashDriver structure - * - * @notapi - */ -void efl_lld_start(EFlashDriver *eflp) { - - stm32_flash_unlock(eflp); - FLASH->CR = 0x00000000U; -} - -/** - * @brief Deactivates the Embedded Flash peripheral. - * - * @param[in] eflp pointer to a @p EFlashDriver structure - * - * @notapi - */ -void efl_lld_stop(EFlashDriver *eflp) { - - stm32_flash_lock(eflp); -} - -/** - * @brief Gets the flash descriptor structure. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @return A flash device descriptor. - * - * @notapi - */ -const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { - - (void)instance; - - return &efl_lld_descriptor; -} - -/** - * @brief Read operation. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] offset flash offset - * @param[in] n number of bytes to be read - * @param[out] rp pointer to the data buffer - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_READ if the read operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_read(void *instance, flash_offset_t offset, - size_t n, uint8_t *rp) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err = FLASH_NO_ERROR; - - osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); - osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No reading while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_READY state while the operation is performed.*/ - devp->state = FLASH_READ; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Actual read implementation.*/ - memcpy((void *)rp, (const void *)efl_lld_descriptor.address + offset, n); - - /* Checking for errors after reading.*/ - if ((devp->flash->SR & FLASH_SR_RDERR) != 0U) { - err = FLASH_ERROR_READ; - } - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; - -} - -/** - * @brief Program operation. - * @note The device supports ECC, it is only possible to write erased - * pages once except when writing all zeroes. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] offset flash offset - * @param[in] n number of bytes to be programmed - * @param[in] pp pointer to the data buffer - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_PROGRAM if the program operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_program(void *instance, flash_offset_t offset, - size_t n, const uint8_t *pp) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err = FLASH_NO_ERROR; - - osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); - osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); - - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No programming while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_PGM; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Enabling PGM mode in the controller.*/ - stm32_flash_enable_pgm(devp); - - /* Actual program implementation.*/ - while (n > 0U) { - volatile uint32_t *address; - - union { - uint32_t w[STM32_FLASH_LINE_SIZE / sizeof (uint32_t)]; - uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)]; - } line; - - /* Unwritten bytes are initialized to all ones.*/ - line.w[0] = 0xFFFFFFFFU; - line.w[1] = 0xFFFFFFFFU; - - /* Programming address aligned to flash lines.*/ - address = (volatile uint32_t *)(efl_lld_descriptor.address + - (offset & ~STM32_FLASH_LINE_MASK)); - - /* Copying data inside the prepared line.*/ - do { - line.b[offset & STM32_FLASH_LINE_MASK] = *pp; - offset++; - n--; - pp++; - } - while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U)); - - /* Programming line.*/ - address[0] = line.w[0]; - address[1] = line.w[1]; - stm32_flash_wait_busy(devp); - err = stm32_flash_check_errors(devp); - if (err != FLASH_NO_ERROR) { - break; - } - } - - /* Disabling PGM mode in the controller.*/ - stm32_flash_disable_pgm(devp); - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -/** - * @brief Starts a whole-device erase operation. - * @note This function only erases bank 2 if it is present. Bank 1 is not - * touched because it is where the program is running on. - * Pages on bank 1 can be individually erased. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_start_erase_all(void *instance) { - EFlashDriver *devp = (EFlashDriver *)instance; - - osalDbgCheck(instance != NULL); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No erasing while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_ERASE; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - -#if defined(FLASH_CR_MER2) - devp->flash->CR |= FLASH_CR_MER2; - devp->flash->CR |= FLASH_CR_STRT; -#endif - - return FLASH_NO_ERROR; -} - -/** - * @brief Starts an sector erase operation. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] sector sector to be erased - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_start_erase_sector(void *instance, - flash_sector_t sector) { - EFlashDriver *devp = (EFlashDriver *)instance; - - osalDbgCheck(instance != NULL); - osalDbgCheck(sector < efl_lld_descriptor.sectors_count); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No erasing while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* FLASH_PGM state while the operation is performed.*/ - devp->state = FLASH_ERASE; - - /* Clearing error status bits.*/ - stm32_flash_clear_status(devp); - - /* Enable page erase.*/ - devp->flash->CR |= FLASH_CR_PER; - -#if defined(FLASH_CR_BKER) - /* Bank selection.*/ - if (sector < STM32_FLASH_SECTORS_PER_BANK) { - /* First bank.*/ - devp->flash->CR &= ~FLASH_CR_BKER; - } - else { - /* Second bank.*/ - devp->flash->CR |= FLASH_CR_BKER; - } -#endif - - /* Mask off the page selection bits.*/ - devp->flash->CR &= ~FLASH_CR_PNB; - - /* Set the page selection bits.*/ - devp->flash->CR |= sector << FLASH_CR_PNB_Pos; - - /* Start the erase.*/ - devp->flash->CR |= FLASH_CR_STRT; - - return FLASH_NO_ERROR; -} - -/** - * @brief Queries the driver for erase operation progress. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[out] msec recommended time, in milliseconds, that - * should be spent before calling this - * function again, can be @p NULL - * @return An error code. - * @retval FLASH_NO_ERROR if there is no erase operation in progress. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_ERASE if the erase operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @api - */ -flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) { - EFlashDriver *devp = (EFlashDriver *)instance; - flash_error_t err; - - /* If there is an erase in progress then the device must be checked.*/ - if (devp->state == FLASH_ERASE) { - - /* Checking for operation in progress.*/ - if ((devp->flash->SR & FLASH_SR_BSY) == 0U) { - - /* Disabling the various erase control bits.*/ - devp->flash->CR &= ~(FLASH_CR_MER1 | -#if defined(FLASH_CR_MER2) - FLASH_CR_MER2 | -#endif - FLASH_CR_PER); - - /* No operation in progress, checking for errors.*/ - err = stm32_flash_check_errors(devp); - - /* Back to ready state.*/ - devp->state = FLASH_READY; - } - else { - /* Recommended time before polling again, this is a simplified - implementation.*/ - if (msec != NULL) { - *msec = (uint32_t)STM32_FLASH_WAIT_TIME_MS; - } - - err = FLASH_BUSY_ERASING; - } - } - else { - err = FLASH_NO_ERROR; - } - - return err; -} - -/** - * @brief Returns the erase state of a sector. - * - * @param[in] ip pointer to a @p EFlashDriver instance - * @param[in] sector sector to be verified - * @return An error code. - * @retval FLASH_NO_ERROR if the sector is erased. - * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. - * @retval FLASH_ERROR_VERIFY if the verify operation failed. - * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. - * - * @notapi - */ -flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { - EFlashDriver *devp = (EFlashDriver *)instance; - uint32_t *address; - flash_error_t err = FLASH_NO_ERROR; - unsigned i; - - osalDbgCheck(instance != NULL); - osalDbgCheck(sector < efl_lld_descriptor.sectors_count); - osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), - "invalid state"); - - /* No verifying while erasing.*/ - if (devp->state == FLASH_ERASE) { - return FLASH_BUSY_ERASING; - } - - /* Address of the sector.*/ - address = (uint32_t *)(efl_lld_descriptor.address + - flashGetSectorOffset(getBaseFlash(devp), sector)); - - /* FLASH_READY state while the operation is performed.*/ - devp->state = FLASH_READ; - - /* Scanning the sector space.*/ - for (i = 0U; i < STM32_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) { - if (*address != 0xFFFFFFFFU) { - err = FLASH_ERROR_VERIFY; - break; - } - address++; - } - - /* Ready state again.*/ - devp->state = FLASH_READY; - - return err; -} - -#endif /* HAL_USE_EFL == TRUE */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_efl_lld.c + * @brief STM32L4xx Embedded Flash subsystem low level driver source. + * + * @addtogroup HAL_EFL + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define STM32_FLASH_SECTOR_SIZE 2048U +#define STM32_FLASH_LINE_SIZE 8U +#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U) + +#define FLASH_PDKEY1 0x04152637U +#define FLASH_PDKEY2 0xFAFBFCFDU + +#define FLASH_KEY1 0x45670123U +#define FLASH_KEY2 0xCDEF89ABU + +#define FLASH_OPTKEY1 0x08192A3BU +#define FLASH_OPTKEY2 0x4C5D6E7FU + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EFL1 driver identifier. + */ +EFlashDriver EFLD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const flash_descriptor_t efl_lld_descriptor = { + .attributes = FLASH_ATTR_ERASED_IS_ONE | + FLASH_ATTR_MEMORY_MAPPED | + FLASH_ATTR_ECC_CAPABLE | + FLASH_ATTR_ECC_ZERO_LINE_CAPABLE, + .page_size = STM32_FLASH_LINE_SIZE, + .sectors_count = STM32_FLASH_NUMBER_OF_BANKS * + STM32_FLASH_SECTORS_PER_BANK, + .sectors = NULL, + .sectors_size = STM32_FLASH_SECTOR_SIZE, + .address = (uint8_t *)0x08000000U, + .size = STM32_FLASH_NUMBER_OF_BANKS * + STM32_FLASH_SECTORS_PER_BANK * + STM32_FLASH_SECTOR_SIZE +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static inline void stm32_flash_lock(EFlashDriver *eflp) { + + eflp->flash->CR |= FLASH_CR_LOCK; +} + +static inline void stm32_flash_unlock(EFlashDriver *eflp) { + + eflp->flash->KEYR |= FLASH_KEY1; + eflp->flash->KEYR |= FLASH_KEY2; +} + +static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) { + + eflp->flash->CR |= FLASH_CR_PG; +} + +static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) { + + eflp->flash->CR &= ~FLASH_CR_PG; +} + +static inline void stm32_flash_clear_status(EFlashDriver *eflp) { + + eflp->flash->SR = 0x0000FFFFU; +} + +static inline void stm32_flash_wait_busy(EFlashDriver *eflp) { + + /* Wait for busy bit clear.*/ + while ((eflp->flash->SR & FLASH_SR_BSY) != 0U) { + } +} + +static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) { + uint32_t sr = eflp->flash->SR; + + /* Clearing error conditions.*/ + eflp->flash->SR = sr & 0x0000FFFFU; + + /* Some errors are only caught by assertion.*/ + osalDbgAssert((sr & (FLASH_SR_FASTERR | + FLASH_SR_MISERR | + FLASH_SR_SIZERR)) == 0U, "unexpected flash error"); + + /* Decoding relevant errors.*/ + if ((sr & FLASH_SR_WRPERR) != 0U) { + return FLASH_ERROR_HW_FAILURE; + } + + if ((sr & (FLASH_SR_PGAERR | FLASH_SR_PROGERR | FLASH_SR_OPERR)) != 0U) { + return eflp->state == FLASH_PGM ? FLASH_ERROR_PROGRAM : FLASH_ERROR_ERASE; + } + + return FLASH_NO_ERROR; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level Embedded Flash driver initialization. + * + * @notapi + */ +void efl_lld_init(void) { + + /* Driver initialization.*/ + eflObjectInit(&EFLD1); + EFLD1.flash = FLASH; +} + +/** + * @brief Configures and activates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_start(EFlashDriver *eflp) { + + stm32_flash_unlock(eflp); + FLASH->CR = 0x00000000U; +} + +/** + * @brief Deactivates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_stop(EFlashDriver *eflp) { + + stm32_flash_lock(eflp); +} + +/** + * @brief Gets the flash descriptor structure. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @return A flash device descriptor. + * + * @notapi + */ +const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { + + (void)instance; + + return &efl_lld_descriptor; +} + +/** + * @brief Read operation. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] offset flash offset + * @param[in] n number of bytes to be read + * @param[out] rp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_READ if the read operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No reading while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_READY state while the operation is performed.*/ + devp->state = FLASH_READ; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Actual read implementation.*/ + memcpy((void *)rp, (const void *)efl_lld_descriptor.address + offset, n); + + /* Checking for errors after reading.*/ + if ((devp->flash->SR & FLASH_SR_RDERR) != 0U) { + err = FLASH_ERROR_READ; + } + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; + +} + +/** + * @brief Program operation. + * @note The device supports ECC, it is only possible to write erased + * pages once except when writing all zeroes. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] offset flash offset + * @param[in] n number of bytes to be programmed + * @param[in] pp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_PROGRAM if the program operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); + + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No programming while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_PGM; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Enabling PGM mode in the controller.*/ + stm32_flash_enable_pgm(devp); + + /* Actual program implementation.*/ + while (n > 0U) { + volatile uint32_t *address; + + union { + uint32_t w[STM32_FLASH_LINE_SIZE / sizeof (uint32_t)]; + uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)]; + } line; + + /* Unwritten bytes are initialized to all ones.*/ + line.w[0] = 0xFFFFFFFFU; + line.w[1] = 0xFFFFFFFFU; + + /* Programming address aligned to flash lines.*/ + address = (volatile uint32_t *)(efl_lld_descriptor.address + + (offset & ~STM32_FLASH_LINE_MASK)); + + /* Copying data inside the prepared line.*/ + do { + line.b[offset & STM32_FLASH_LINE_MASK] = *pp; + offset++; + n--; + pp++; + } + while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U)); + + /* Programming line.*/ + address[0] = line.w[0]; + address[1] = line.w[1]; + stm32_flash_wait_busy(devp); + err = stm32_flash_check_errors(devp); + if (err != FLASH_NO_ERROR) { + break; + } + } + + /* Disabling PGM mode in the controller.*/ + stm32_flash_disable_pgm(devp); + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +/** + * @brief Starts a whole-device erase operation. + * @note This function only erases bank 2 if it is present. Bank 1 is not + * touched because it is where the program is running on. + * Pages on bank 1 can be individually erased. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_all(void *instance) { + EFlashDriver *devp = (EFlashDriver *)instance; + + osalDbgCheck(instance != NULL); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No erasing while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_ERASE; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + +#if defined(FLASH_CR_MER2) + devp->flash->CR |= FLASH_CR_MER2; + devp->flash->CR |= FLASH_CR_STRT; +#endif + + return FLASH_NO_ERROR; +} + +/** + * @brief Starts an sector erase operation. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] sector sector to be erased + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < efl_lld_descriptor.sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No erasing while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed.*/ + devp->state = FLASH_ERASE; + + /* Clearing error status bits.*/ + stm32_flash_clear_status(devp); + + /* Enable page erase.*/ + devp->flash->CR |= FLASH_CR_PER; + +#if defined(FLASH_CR_BKER) + /* Bank selection.*/ + if (sector < STM32_FLASH_SECTORS_PER_BANK) { + /* First bank.*/ + devp->flash->CR &= ~FLASH_CR_BKER; + } + else { + /* Second bank.*/ + devp->flash->CR |= FLASH_CR_BKER; + } +#endif + + /* Mask off the page selection bits.*/ + devp->flash->CR &= ~FLASH_CR_PNB; + + /* Set the page selection bits.*/ + devp->flash->CR |= sector << FLASH_CR_PNB_Pos; + + /* Start the erase.*/ + devp->flash->CR |= FLASH_CR_STRT; + + return FLASH_NO_ERROR; +} + +/** + * @brief Queries the driver for erase operation progress. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[out] msec recommended time, in milliseconds, that + * should be spent before calling this + * function again, can be @p NULL + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_ERASE if the erase operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @api + */ +flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err; + + /* If there is an erase in progress then the device must be checked.*/ + if (devp->state == FLASH_ERASE) { + + /* Checking for operation in progress.*/ + if ((devp->flash->SR & FLASH_SR_BSY) == 0U) { + + /* Disabling the various erase control bits.*/ + devp->flash->CR &= ~(FLASH_CR_MER1 | +#if defined(FLASH_CR_MER2) + FLASH_CR_MER2 | +#endif + FLASH_CR_PER); + + /* No operation in progress, checking for errors.*/ + err = stm32_flash_check_errors(devp); + + /* Back to ready state.*/ + devp->state = FLASH_READY; + } + else { + /* Recommended time before polling again, this is a simplified + implementation.*/ + if (msec != NULL) { + *msec = (uint32_t)STM32_FLASH_WAIT_TIME_MS; + } + + err = FLASH_BUSY_ERASING; + } + } + else { + err = FLASH_NO_ERROR; + } + + return err; +} + +/** + * @brief Returns the erase state of a sector. + * + * @param[in] ip pointer to a @p EFlashDriver instance + * @param[in] sector sector to be verified + * @return An error code. + * @retval FLASH_NO_ERROR if the sector is erased. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_VERIFY if the verify operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + uint32_t *address; + flash_error_t err = FLASH_NO_ERROR; + unsigned i; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < efl_lld_descriptor.sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No verifying while erasing.*/ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* Address of the sector.*/ + address = (uint32_t *)(efl_lld_descriptor.address + + flashGetSectorOffset(getBaseFlash(devp), sector)); + + /* FLASH_READY state while the operation is performed.*/ + devp->state = FLASH_READ; + + /* Scanning the sector space.*/ + for (i = 0U; i < STM32_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) { + if (*address != 0xFFFFFFFFU) { + err = FLASH_ERROR_VERIFY; + break; + } + address++; + } + + /* Ready state again.*/ + devp->state = FLASH_READY; + + return err; +} + +#endif /* HAL_USE_EFL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h b/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h index 774e8ae457..5ee31c5b68 100644 --- a/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h +++ b/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h @@ -1,116 +1,116 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal_efl_lld.h - * @brief STM32L4xx Embedded Flash subsystem low level driver header. - * - * @addtogroup HAL_EFL - * @{ - */ - -#ifndef HAL_EFL_LLD_H -#define HAL_EFL_LLD_H - -#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name STM32L4xx configuration options - * @{ - */ -/** - * @brief Suggested wait time during erase operations polling. - */ -#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) -#define STM32_FLASH_WAIT_TIME_MS 5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !defined(STM32_FLASH_NUMBER_OF_BANKS) -#error "STM32_FLASH_NUMBER_OF_BANKS not defined in registry" -#endif - -#if !defined(STM32_FLASH_SECTORS_PER_BANK) -#error "STM32_FLASH_SECTORS_PER_BANK not defined in registry" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Low level fields of the embedded flash driver structure. - */ -#define efl_lld_driver_fields \ - /* Flash registers.*/ \ - FLASH_TypeDef *flash - -/** - * @brief Low level fields of the embedded flash configuration structure. - */ -#define efl_lld_config_fields \ - /* Dummy configuration, it is not needed.*/ \ - uint32_t dummy - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern EFlashDriver EFLD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void efl_lld_init(void); - void efl_lld_start(EFlashDriver *eflp); - void efl_lld_stop(EFlashDriver *eflp); - const flash_descriptor_t *efl_lld_get_descriptor(void *instance); - flash_error_t efl_lld_read(void *instance, flash_offset_t offset, - size_t n, uint8_t *rp); - flash_error_t efl_lld_program(void *instance, flash_offset_t offset, - size_t n, const uint8_t *pp); - flash_error_t efl_lld_start_erase_all(void *instance); - flash_error_t efl_lld_start_erase_sector(void *instance, - flash_sector_t sector); - flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec); - flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EFL == TRUE */ - -#endif /* HAL_EFL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_efl_lld.h + * @brief STM32L4xx Embedded Flash subsystem low level driver header. + * + * @addtogroup HAL_EFL + * @{ + */ + +#ifndef HAL_EFL_LLD_H +#define HAL_EFL_LLD_H + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name STM32L4xx configuration options + * @{ + */ +/** + * @brief Suggested wait time during erase operations polling. + */ +#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) +#define STM32_FLASH_WAIT_TIME_MS 5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_FLASH_NUMBER_OF_BANKS) +#error "STM32_FLASH_NUMBER_OF_BANKS not defined in registry" +#endif + +#if !defined(STM32_FLASH_SECTORS_PER_BANK) +#error "STM32_FLASH_SECTORS_PER_BANK not defined in registry" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the embedded flash driver structure. + */ +#define efl_lld_driver_fields \ + /* Flash registers.*/ \ + FLASH_TypeDef *flash + +/** + * @brief Low level fields of the embedded flash configuration structure. + */ +#define efl_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern EFlashDriver EFLD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void efl_lld_init(void); + void efl_lld_start(EFlashDriver *eflp); + void efl_lld_stop(EFlashDriver *eflp); + const flash_descriptor_t *efl_lld_get_descriptor(void *instance); + flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp); + flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp); + flash_error_t efl_lld_start_erase_all(void *instance); + flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector); + flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec); + flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EFL == TRUE */ + +#endif /* HAL_EFL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/hal_lld.c b/os/hal/ports/STM32/STM32L4xx/hal_lld.c index 4e3fc566b2..012337cf56 100644 --- a/os/hal/ports/STM32/STM32L4xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32L4xx/hal_lld.c @@ -1,399 +1,399 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx/hal_lld.c - * @brief STM32L4xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief CMSIS system core clock variable. - * @note It is declared in system_stm32f7xx.h. - */ -uint32_t SystemCoreClock = STM32_HCLK; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing RTC clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - int rusefiLseCounter = 0; - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - /* Waits until LSE is stable or times out. */ - while ((!RUSEFI_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < RUSEFI_STM32_LSE_WAIT_MAX) - && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; -#endif - -#if STM32_MSIPLL_ENABLED - /* MSI PLL activation depends on LSE. Reactivating and checking for - MSI stability.*/ - RCC->CR |= RCC_CR_MSIPLLEN; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; /* Wait until MSI is stable. */ -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ -#if STM32_LSE_ENABLED - RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; -#else - RCC->BDCR |= STM32_RTCSEL; -#endif - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - - /* Low speed output mode.*/ - RCC->BDCR |= STM32_LSCOSEL; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. - Note, GPIOs are not reset because initialized before this point in - board files.*/ - rccResetAHB1(~0); - rccResetAHB2(~STM32_GPIO_EN_MASK); - rccResetAHB3(~0); - rccResetAPB1R1(~RCC_APB1RSTR1_PWRRST); - rccResetAPB1R2(~0); - rccResetAPB2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(true); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - - /* DMA subsystems initialization.*/ -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* IRQ subsystem initialization.*/ - irqInit(); - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK); -#else - PWR->CR2 = 0; -#endif /* STM32_PVD_ENABLE */ - - /* Enabling independent VDDUSB.*/ -#if HAL_USE_USB - PWR->CR2 |= PWR_CR2_USV; -#endif /* HAL_USE_USB */ - - /* Enabling independent VDDIO2 required by GPIOG.*/ -#if STM32_HAS_GPIOG - PWR->CR2 |= PWR_CR2_IOSV; -#endif /* STM32_HAS_GPIOG */ -} - -/** - * @brief STM32L4xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ -#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR1_RTCAPBEN) - RCC->APB1ENR1 = RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN; -#else - RCC->APB1ENR1 = RCC_APB1ENR1_PWREN; -#endif - - /* Initial clocks setup and wait for MSI stabilization, the MSI clock is - always enabled because it is the fall back clock when PLL the fails. - Trim fields are not altered from reset values.*/ - - /* MSIRANGE can be set only when MSI is OFF or READY.*/ - RCC->CR = RCC_CR_MSION; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; /* Wait until MSI is stable. */ - - /* Clocking from MSI, in case MSI was not the default source.*/ - RCC->CFGR = 0; - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) - ; /* Wait until MSI is selected. */ - - /* Core voltage setup.*/ - PWR->CR1 = STM32_VOS; - while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ - ; /* stable. */ - -#if STM32_HSI16_ENABLED - /* HSI activation.*/ - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Wait until HSI16 is stable. */ -#endif - -#if STM32_CLOCK_HAS_HSI48 -#if STM32_HSI48_ENABLED - /* HSI activation.*/ - RCC->CRRCR |= RCC_CRRCR_HSI48ON; - while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) - ; /* Wait until HSI48 is stable. */ -#endif -#endif - -#if STM32_HSE_ENABLED -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#endif - /* HSE activation.*/ - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Wait until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Wait until LSI is stable. */ -#endif - - /* Backup domain access enabled and left open.*/ - PWR->CR1 |= PWR_CR1_DBP; - -#if STM32_LSE_ENABLED - /* LSE activation.*/ -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Wait until LSE is stable. */ -#endif - - /* Flash setup for selected MSI speed setting.*/ - FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | - STM32_MSI_FLASHBITS; - - /* Changing MSIRANGE to configured value.*/ - RCC->CR |= STM32_MSIRANGE; - - /* Switching from MSISRANGE to MSIRANGE.*/ - RCC->CR |= RCC_CR_MSIRGSEL; - while ((RCC->CR & RCC_CR_MSIRDY) == 0) - ; - - /* MSI is configured SYSCLK source so wait for it to be stable as well.*/ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) - ; - -#if STM32_MSIPLL_ENABLED - /* MSI PLL (to LSE) activation */ - RCC->CR |= RCC_CR_MSIPLLEN; -#endif - - /* Updating MSISRANGE value. MSISRANGE can be set only when MSIRGSEL is high. - This range is used exiting the Standby mode until MSIRGSEL is set.*/ - RCC->CSR |= STM32_MSISRANGE; - -#if STM32_ACTIVATE_PLL || STM32_ACTIVATE_PLLSAI1 || STM32_ACTIVATE_PLLSAI2 - /* PLLM and PLLSRC are common to all PLLs.*/ -#if defined(STM32L496xx) || defined(STM32L4A6xx) - RCC->PLLCFGR = STM32_PLLPDIV | STM32_PLLR | - STM32_PLLREN | STM32_PLLQ | - STM32_PLLQEN | STM32_PLLP | - STM32_PLLPEN | STM32_PLLN | - STM32_PLLM | STM32_PLLSRC; -#else - RCC->PLLCFGR = STM32_PLLR | STM32_PLLREN | - STM32_PLLQ | STM32_PLLQEN | - STM32_PLLP | STM32_PLLPEN | - STM32_PLLN | STM32_PLLM | - STM32_PLLSRC; -#endif -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLRDY) == 0) - ; -#endif - -#if STM32_ACTIVATE_PLLSAI1 - /* PLLSAI1 activation.*/ -#if defined(STM32L496xx) || defined(STM32L4A6xx) - RCC->PLLSAI1CFGR = STM32_PLLSAI1PDIV | STM32_PLLSAI1R | - STM32_PLLSAI1REN | STM32_PLLSAI1Q | - STM32_PLLSAI1QEN | STM32_PLLSAI1P | - STM32_PLLSAI1PEN | STM32_PLLSAI1N; -#else - RCC->PLLSAI1CFGR = STM32_PLLSAI1R | STM32_PLLSAI1REN | - STM32_PLLSAI1Q | STM32_PLLSAI1QEN | - STM32_PLLSAI1P | STM32_PLLSAI1PEN | - STM32_PLLSAI1N; -#endif - RCC->CR |= RCC_CR_PLLSAI1ON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLSAI1RDY) == 0) - ; -#endif - -#if STM32_ACTIVATE_PLLSAI2 - /* PLLSAI2 activation.*/ -#if defined(STM32L496xx) || defined(STM32L4A6xx) - RCC->PLLSAI2CFGR = STM32_PLLSAI2PDIV | STM32_PLLSAI2R | - STM32_PLLSAI2REN | STM32_PLLSAI2P | - STM32_PLLSAI2PEN | STM32_PLLSAI2N; -#else - RCC->PLLSAI2CFGR = STM32_PLLSAI2R | STM32_PLLSAI2REN | - STM32_PLLSAI2P | STM32_PLLSAI2PEN | - STM32_PLLSAI2N; -#endif - RCC->CR |= RCC_CR_PLLSAI2ON; - - /* Waiting for PLL lock.*/ - while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0) - ; -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_STOPWUCK | - STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - - /* CCIPR register initialization, note, must take care of the _OFF - pseudo settings.*/ - { - uint32_t ccipr = STM32_DFSDMSEL | STM32_SWPMI1SEL | STM32_ADCSEL | - STM32_CLK48SEL | STM32_LPTIM2SEL | STM32_LPTIM1SEL | - STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | - STM32_UART5SEL | STM32_UART4SEL | STM32_USART3SEL | - STM32_USART2SEL | STM32_USART1SEL | STM32_LPUART1SEL; -#if STM32_SAI2SEL != STM32_SAI2SEL_OFF - ccipr |= STM32_SAI2SEL; -#endif -#if STM32_SAI1SEL != STM32_SAI1SEL_OFF - ccipr |= STM32_SAI1SEL; -#endif - RCC->CCIPR = ccipr; - } - -#if STM32_HAS_I2C4 - /* CCIPR2 register initialization.*/ - { - uint32_t ccipr2 = STM32_I2C4SEL; - RCC->CCIPR2 = ccipr2; - } -#endif - - /* Set flash WS's for SYSCLK source */ - if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) { - FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - } - - /* Switching to the configured SYSCLK source if it is different from MSI.*/ -#if (STM32_SW != STM32_SW_MSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - /* Wait until SYSCLK is stable.*/ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif - - /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */ - if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) { - FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != - (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { - } - } - -#endif /* STM32_NO_INIT */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx/hal_lld.c + * @brief STM32L4xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_stm32f7xx.h. + */ +uint32_t SystemCoreClock = STM32_HCLK; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing RTC clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + int rusefiLseCounter = 0; + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + /* Waits until LSE is stable or times out. */ + while ((!FOME_STM32_LSE_WAIT_MAX || rusefiLseCounter++ < FOME_STM32_LSE_WAIT_MAX) + && (RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; +#endif + +#if STM32_MSIPLL_ENABLED + /* MSI PLL activation depends on LSE. Reactivating and checking for + MSI stability.*/ + RCC->CR |= RCC_CR_MSIPLLEN; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; /* Wait until MSI is stable. */ +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ +#if STM32_LSE_ENABLED + RCC->BDCR |= (RCC->BDCR & RCC_BDCR_LSERDY) == 0 ? FOME_STM32_LSE_WAIT_MAX_RTCSEL : STM32_RTCSEL; +#else + RCC->BDCR |= STM32_RTCSEL; +#endif + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + + /* Low speed output mode.*/ + RCC->BDCR |= STM32_LSCOSEL; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. + Note, GPIOs are not reset because initialized before this point in + board files.*/ + rccResetAHB1(~0); + rccResetAHB2(~STM32_GPIO_EN_MASK); + rccResetAHB3(~0); + rccResetAPB1R1(~RCC_APB1RSTR1_PWRRST); + rccResetAPB1R2(~0); + rccResetAPB2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(true); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + + /* DMA subsystems initialization.*/ +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* IRQ subsystem initialization.*/ + irqInit(); + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK); +#else + PWR->CR2 = 0; +#endif /* STM32_PVD_ENABLE */ + + /* Enabling independent VDDUSB.*/ +#if HAL_USE_USB + PWR->CR2 |= PWR_CR2_USV; +#endif /* HAL_USE_USB */ + + /* Enabling independent VDDIO2 required by GPIOG.*/ +#if STM32_HAS_GPIOG + PWR->CR2 |= PWR_CR2_IOSV; +#endif /* STM32_HAS_GPIOG */ +} + +/** + * @brief STM32L4xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ +#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR1_RTCAPBEN) + RCC->APB1ENR1 = RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN; +#else + RCC->APB1ENR1 = RCC_APB1ENR1_PWREN; +#endif + + /* Initial clocks setup and wait for MSI stabilization, the MSI clock is + always enabled because it is the fall back clock when PLL the fails. + Trim fields are not altered from reset values.*/ + + /* MSIRANGE can be set only when MSI is OFF or READY.*/ + RCC->CR = RCC_CR_MSION; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; /* Wait until MSI is stable. */ + + /* Clocking from MSI, in case MSI was not the default source.*/ + RCC->CFGR = 0; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + ; /* Wait until MSI is selected. */ + + /* Core voltage setup.*/ + PWR->CR1 = STM32_VOS; + while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */ + ; /* stable. */ + +#if STM32_HSI16_ENABLED + /* HSI activation.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Wait until HSI16 is stable. */ +#endif + +#if STM32_CLOCK_HAS_HSI48 +#if STM32_HSI48_ENABLED + /* HSI activation.*/ + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0) + ; /* Wait until HSI48 is stable. */ +#endif +#endif + +#if STM32_HSE_ENABLED +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#endif + /* HSE activation.*/ + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Wait until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Wait until LSI is stable. */ +#endif + + /* Backup domain access enabled and left open.*/ + PWR->CR1 |= PWR_CR1_DBP; + +#if STM32_LSE_ENABLED + /* LSE activation.*/ +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Wait until LSE is stable. */ +#endif + + /* Flash setup for selected MSI speed setting.*/ + FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | + STM32_MSI_FLASHBITS; + + /* Changing MSIRANGE to configured value.*/ + RCC->CR |= STM32_MSIRANGE; + + /* Switching from MSISRANGE to MSIRANGE.*/ + RCC->CR |= RCC_CR_MSIRGSEL; + while ((RCC->CR & RCC_CR_MSIRDY) == 0) + ; + + /* MSI is configured SYSCLK source so wait for it to be stable as well.*/ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + ; + +#if STM32_MSIPLL_ENABLED + /* MSI PLL (to LSE) activation */ + RCC->CR |= RCC_CR_MSIPLLEN; +#endif + + /* Updating MSISRANGE value. MSISRANGE can be set only when MSIRGSEL is high. + This range is used exiting the Standby mode until MSIRGSEL is set.*/ + RCC->CSR |= STM32_MSISRANGE; + +#if STM32_ACTIVATE_PLL || STM32_ACTIVATE_PLLSAI1 || STM32_ACTIVATE_PLLSAI2 + /* PLLM and PLLSRC are common to all PLLs.*/ +#if defined(STM32L496xx) || defined(STM32L4A6xx) + RCC->PLLCFGR = STM32_PLLPDIV | STM32_PLLR | + STM32_PLLREN | STM32_PLLQ | + STM32_PLLQEN | STM32_PLLP | + STM32_PLLPEN | STM32_PLLN | + STM32_PLLM | STM32_PLLSRC; +#else + RCC->PLLCFGR = STM32_PLLR | STM32_PLLREN | + STM32_PLLQ | STM32_PLLQEN | + STM32_PLLP | STM32_PLLPEN | + STM32_PLLN | STM32_PLLM | + STM32_PLLSRC; +#endif +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLRDY) == 0) + ; +#endif + +#if STM32_ACTIVATE_PLLSAI1 + /* PLLSAI1 activation.*/ +#if defined(STM32L496xx) || defined(STM32L4A6xx) + RCC->PLLSAI1CFGR = STM32_PLLSAI1PDIV | STM32_PLLSAI1R | + STM32_PLLSAI1REN | STM32_PLLSAI1Q | + STM32_PLLSAI1QEN | STM32_PLLSAI1P | + STM32_PLLSAI1PEN | STM32_PLLSAI1N; +#else + RCC->PLLSAI1CFGR = STM32_PLLSAI1R | STM32_PLLSAI1REN | + STM32_PLLSAI1Q | STM32_PLLSAI1QEN | + STM32_PLLSAI1P | STM32_PLLSAI1PEN | + STM32_PLLSAI1N; +#endif + RCC->CR |= RCC_CR_PLLSAI1ON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLSAI1RDY) == 0) + ; +#endif + +#if STM32_ACTIVATE_PLLSAI2 + /* PLLSAI2 activation.*/ +#if defined(STM32L496xx) || defined(STM32L4A6xx) + RCC->PLLSAI2CFGR = STM32_PLLSAI2PDIV | STM32_PLLSAI2R | + STM32_PLLSAI2REN | STM32_PLLSAI2P | + STM32_PLLSAI2PEN | STM32_PLLSAI2N; +#else + RCC->PLLSAI2CFGR = STM32_PLLSAI2R | STM32_PLLSAI2REN | + STM32_PLLSAI2P | STM32_PLLSAI2PEN | + STM32_PLLSAI2N; +#endif + RCC->CR |= RCC_CR_PLLSAI2ON; + + /* Waiting for PLL lock.*/ + while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0) + ; +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_STOPWUCK | + STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + + /* CCIPR register initialization, note, must take care of the _OFF + pseudo settings.*/ + { + uint32_t ccipr = STM32_DFSDMSEL | STM32_SWPMI1SEL | STM32_ADCSEL | + STM32_CLK48SEL | STM32_LPTIM2SEL | STM32_LPTIM1SEL | + STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL | + STM32_UART5SEL | STM32_UART4SEL | STM32_USART3SEL | + STM32_USART2SEL | STM32_USART1SEL | STM32_LPUART1SEL; +#if STM32_SAI2SEL != STM32_SAI2SEL_OFF + ccipr |= STM32_SAI2SEL; +#endif +#if STM32_SAI1SEL != STM32_SAI1SEL_OFF + ccipr |= STM32_SAI1SEL; +#endif + RCC->CCIPR = ccipr; + } + +#if STM32_HAS_I2C4 + /* CCIPR2 register initialization.*/ + { + uint32_t ccipr2 = STM32_I2C4SEL; + RCC->CCIPR2 = ccipr2; + } +#endif + + /* Set flash WS's for SYSCLK source */ + if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) { + FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + } + + /* Switching to the configured SYSCLK source if it is different from MSI.*/ +#if (STM32_SW != STM32_SW_MSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + /* Wait until SYSCLK is stable.*/ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif + + /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */ + if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) { + FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS; + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != + (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) { + } + } + +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/hal_lld.h b/os/hal/ports/STM32/STM32L4xx/hal_lld.h index 0aae22a844..3d34317470 100644 --- a/os/hal/ports/STM32/STM32L4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32L4xx/hal_lld.h @@ -1,2368 +1,2376 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx/hal_lld.h - * @brief STM32L4xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32L432xx, STM32L433xx, STM32L443xx. - * - STM32L471xx, STM32L475xx, STM32L476xx, STM32L496xx. - * - STM32L485xx, STM32L486xx, STM32L4A6xx. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L443xx) || \ - defined(STM32L452xx) || defined(STM32L471xx) || defined(STM32L475xx) || \ - defined(STM32L476xx) || defined(STM32L496xx) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32L4xx Ultra Low Power" - -#elif defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L4A6xx) -#define PLATFORM_NAME "STM32L4xx Ultra Low Power with Crypto" - -#else -#error "STM32L4xx device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32L4XX) || defined(__DOXYGEN__) -#define STM32L4XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ -#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR1 register bits definitions - * @{ - */ -#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */ -#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */ -#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ -/** @} */ - -/** - * @name PWR_CR2 register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ -#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CR register bits definitions - * @{ - */ -#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */ -#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */ -#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */ -#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */ -#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */ -#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */ -#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */ -#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */ -#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */ -#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */ -#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */ -#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */ -#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ -#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ -#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */ -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */ -#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */ -#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */ - -#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ -#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ - -#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ -#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ -#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ -#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ -#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ -#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */ -#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CCIPR register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ -#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ -#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ -#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */ -#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ - -#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ -#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ -#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ -#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */ -#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ - -#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ -#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ -#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ -#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */ -#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ - -#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ -#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ -#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ -#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */ -#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ - -#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ -#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ -#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ -#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */ -#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ - -#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */ -#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */ -#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */ -#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */ -#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */ - -#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */ -#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */ - -#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */ -#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */ -#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */ -#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */ - -#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */ -#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */ -#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */ -#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */ - -#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */ -#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */ -#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */ -#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */ - -#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */ -#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */ -#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */ -#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */ -#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */ - -#define STM32_SAI1SEL_MASK (3 << 22) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_PLLSAI1 (0 << 22) /**< SAI1 source is PLLSAI1-P. */ -#define STM32_SAI1SEL_PLLSAI2 (1 << 22) /**< SAI1 source is PLLSAI2-P. */ -#define STM32_SAI1SEL_PLL (2 << 22) /**< SAI1 source is PLL-P. */ -#define STM32_SAI1SEL_EXTCLK (3 << 22) /**< SAI1 source is external. */ -#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ - -#define STM32_SAI2SEL_MASK (3 << 24) /**< SAI2SEL mask. */ -#define STM32_SAI2SEL_PLLSAI1 (0 << 24) /**< SAI2 source is PLLSAI1-P. */ -#define STM32_SAI2SEL_PLLSAI2 (1 << 24) /**< SAI2 source is PLLSAI2-P. */ -#define STM32_SAI2SEL_PLL (2 << 24) /**< SAI2 source is PLL-P. */ -#define STM32_SAI2SEL_EXTCLK (3 << 24) /**< SAI2 source is external. */ -#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ - -#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */ -#if !STM32_CLOCK_HAS_HSI48 -#define STM32_CLK48SEL_NOCLK (0 << 26) /**< CLK48 disabled. */ -#else -#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */ -#endif -#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */ -#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */ -#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */ - -#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */ -#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */ -#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */ -#define STM32_ADCSEL_PLLSAI2 (2 << 28) /**< ADC source is PLLSAI2-R. */ -#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */ - -#define STM32_SWPMI1SEL_MASK (1 << 30) /**< SWPMI1SEL mask. */ -#define STM32_SWPMI1SEL_PCLK1 (0 << 30) /**< SWPMI1 source is PCLK1. */ -#define STM32_SWPMI1SEL_HSI16 (1 << 30) /**< SWPMI1 source is HSI16. */ - -#define STM32_DFSDMSEL_MASK (1 << 31) /**< DFSDMSEL mask. */ -#define STM32_DFSDMSEL_PCLK2 (0 << 31) /**< DFSDM source is PCLK2. */ -#define STM32_DFSDMSEL_SYSCLK (1 << 31) /**< DFSDM source is SYSCLK. */ -/** @} */ - -/** - * @name RCC_CCIPR2 register bits definitions - * @{ - */ -#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */ -#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */ -#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */ -/** @} */ - -/** - * @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. */ - -#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */ -#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */ -#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */ -#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */ -/** @} */ - -/** - * @name RCC_CSR register bits definitions - * @{ - */ -#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */ -#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */ -#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */ -#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */ -#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_RANGE1 -#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 HSI16 clock source. - */ -#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSI48 clock source. - */ -#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI48_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief Enables or disables the MSI PLL on LSE clock source. - */ -#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__) -#define STM32_MSIPLL_ENABLED FALSE -#endif - -/** - * @brief MSI frequency setting. - */ -#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) -#define STM32_MSIRANGE STM32_MSIRANGE_4M -#endif - -/** - * @brief MSI frequency setting after standby. - */ -#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__) -#define STM32_MSISRANGE STM32_MSISRANGE_4M -#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 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_MSI -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 1..8. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 1 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 8..86. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 80 -#endif - -/** - * @brief PLLPDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLPDIV_VALUE 0 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 7, 17. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 7 -#endif - -/** - * @brief PLLQ divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 6 -#endif - -/** - * @brief PLLR divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLR_VALUE 4 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 80MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief STOPWUCK clock setting. - */ -#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) -#define STM32_STOPWUCK STM32_STOPWUCK_MSI -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief LSCO clock source. - */ -#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#endif - -/** - * @brief PLLSAI1N multiplier value. - * @note The allowed values are 8..86. - */ -#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1N_VALUE 80 -#endif - -/** - * @brief PLLSAI1PDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1PDIV_VALUE 0 -#endif - -/** - * @brief PLLSAI1P divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1P_VALUE 7 -#endif - -/** - * @brief PLLSAI1Q divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1Q_VALUE 6 -#endif - -/** - * @brief PLLSAI1R divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1R_VALUE 4 -#endif - -/** - * @brief PLLSAI2N multiplier value. - * @note The allowed values are 8..86. - */ -#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2N_VALUE 80 -#endif - -/** - * @brief PLLSAI2PDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2PDIV_VALUE 0 -#endif - -/** - * @brief PLLSAI2P divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2P_VALUE 7 -#endif - -/** - * @brief PLLSAI2R divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2R_VALUE 4 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) -#define STM32_UART5SEL STM32_UART5SEL_SYSCLK -#endif - -/** - * @brief LPUART1 clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) -#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK -#endif - -/** - * @brief I2C3 clock source. - */ -#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) -#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK -#endif - -/** - * @brief I2C4 clock source. - */ -#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) -#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#endif - -/** - * @brief LPTIM2 clock source. - */ -#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 -#endif - -/** - * @brief SAI1SEL value (SAI1 clock source). - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#endif - -/** - * @brief SAI2SEL value (SAI2 clock source). - */ -#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#endif - -/** - * @brief CLK48SEL value (48MHz clock source). - */ -#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) -#define STM32_CLK48SEL STM32_CLK48SEL_PLL -#endif - -/** - * @brief ADCSEL value (ADCs clock source). - */ -#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) -#define STM32_ADCSEL STM32_ADCSEL_SYSCLK -#endif - -/** - * @brief SWPMI1SEL value (SWPMI clock source). - */ -#if !defined(STM32_SWPMI1SEL) || defined(__DOXYGEN__) -#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 -#endif - -/** - * @brief DFSDMSEL value (DFSDM clock source). - */ -#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__) -#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 -#endif - -/** - * @brief RTC/LCD clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32L4xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4xx_MCUCONF not defined" -#endif - -/* Only some devices have strongly checked mcuconf.h files. Others will be - added gradually.*/ -#if defined(STM32L432xx) && !defined(STM32L432_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L432_MCUCONF not defined" -#endif - -#if defined(STM32L433xx) && !defined(STM32L433_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L433_MCUCONF not defined" -#endif - -#if defined(STM32L476xx) && !defined(STM32L476_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L476_MCUCONF not defined" -#endif - -#if defined(STM32L486xx) && !defined(STM32L486_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L486_MCUCONF not defined" -#endif - -#if defined(STM32L496xx) && !defined(STM32L496_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L496_MCUCONF not defined" -#endif - -#if defined(STM32L4A6xx) && !defined(STM32L4A6_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L4A6_MCUCONF not defined" -#endif - -/* - * Board files sanity checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif - -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) -/** - * @name System Limits - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency at current voltage setting. - */ -#define STM32_SYSCLK_MAX 80000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 48000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 8000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 4000000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 344000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 64000000 - -/** - * @brief Maximum PLL-P output clock frequency. - */ -#define STM32_PLLP_MAX 80000000 - -/** - * @brief Minimum PLL-P output clock frequency. - */ -#define STM32_PLLP_MIN 2064500 - -/** - * @brief Maximum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MAX 80000000 - -/** - * @brief Minimum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MIN 8000000 - -/** - * @brief Maximum PLL-R output clock frequency. - */ -#define STM32_PLLR_MAX 80000000 - -/** - * @brief Minimum PLL-R output clock frequency. - */ -#define STM32_PLLR_MIN 8000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 80000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 80000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 80000000 -/** @} */ - -/** - * @name Flash Wait states - * @{ - */ -#define STM32_0WS_THRESHOLD 16000000 -#define STM32_1WS_THRESHOLD 32000000 -#define STM32_2WS_THRESHOLD 48000000 -#define STM32_3WS_THRESHOLD 64000000 -/** @} */ - -#elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 26000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 26000000 -#define STM32_HSECLK_MIN 8000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 4000000 -#define STM32_PLLVCO_MAX 128000000 -#define STM32_PLLVCO_MIN 64000000 -#define STM32_PLLP_MAX 26000000 -#define STM32_PLLP_MIN 2064500 -#define STM32_PLLQ_MAX 26000000 -#define STM32_PLLQ_MIN 8000000 -#define STM32_PLLR_MAX 26000000 -#define STM32_PLLR_MIN 8000000 -#define STM32_PCLK1_MAX 26000000 -#define STM32_PCLK2_MAX 26000000 -#define STM32_ADCCLK_MAX 26000000 - -#define STM32_0WS_THRESHOLD 6000000 -#define STM32_1WS_THRESHOLD 12000000 -#define STM32_2WS_THRESHOLD 18000000 -#define STM32_3WS_THRESHOLD 26000000 - -#else -#error "invalid STM32_VOS value specified" -#endif - -/** - * @brief MSI frequency. - */ -#if STM32_MSIRANGE == STM32_MSIRANGE_100K -#define STM32_MSICLK 100000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_200K -#define STM32_MSICLK 200000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_400K -#define STM32_MSICLK 400000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_800K -#define STM32_MSICLK 800000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_1M -#define STM32_MSICLK 1000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_2M -#define STM32_MSICLK 2000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_4M -#define STM32_MSICLK 4000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_8M -#define STM32_MSICLK 8000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_16M -#define STM32_MSICLK 16000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_24M -#define STM32_MSICLK 24000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_32M -#define STM32_MSICLK 32000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_48M -#define STM32_MSICLK 48000000 -#else -#error "invalid STM32_MSIRANGE value specified" -#endif - -/** - * @brief MSIS frequency. - */ -#if STM32_MSISRANGE == STM32_MSISRANGE_1M -#define STM32_MSISCLK 1000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_2M -#define STM32_MSISCLK 2000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_4M -#define STM32_MSISCLK 4000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_8M -#define STM32_MSISCLK 8000000 -#else -#error "invalid STM32_MSISRANGE value specified" -#endif - -/* - * HSI16 related checks. - */ -#if STM32_HSI16_ENABLED -#else /* !STM32_HSI16_ENABLED */ - -#if STM32_SW == STM32_SW_HSI16 -#error "HSI16 not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16)) -#error "HSI16 not enabled, required by STM32_MCOSEL" -#endif - -#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SAI1SEL" -#endif - -#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16) -#error "HSI16 not enabled, required by STM32_SAI2SEL" -#endif - -#if (STM32_USART1SEL == STM32_USART1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART1SEL" -#endif -#if (STM32_USART2SEL == STM32_USART2SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART2SEL" -#endif -#if (STM32_USART3SEL == STM32_USART3SEL_HSI16) -#error "HSI16 not enabled, required by STM32_USART3SEL" -#endif -#if (STM32_UART4SEL == STM32_UART4SEL_HSI16) -#error "HSI16 not enabled, required by STM32_UART4SEL" -#endif -#if (STM32_UART5SEL == STM32_UART5SEL_HSI16) -#error "HSI16 not enabled, required by STM32_UART5SEL" -#endif -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) -#error "HSI16 not enabled, required by STM32_LPUART1SEL" -#endif - -#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) -#error "HSI16 not enabled, required by I2C1SEL" -#endif -#if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) -#error "HSI16 not enabled, required by I2C2SEL" -#endif -#if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) -#error "HSI16 not enabled, required by I2C3SEL" -#endif -#if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) -#error "HSI16 not enabled, required by I2C4SEL" -#endif - -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) -#error "HSI16 not enabled, required by LPTIM1SEL" -#endif -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) -#error "HSI16 not enabled, required by LPTIM2SEL" -#endif - -#if (STM32_SWPMI1SEL == STM32_SWPMI1SEL_HSI16) -#error "HSI16 not enabled, required by SWPMI1SEL" -#endif -#if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16) -#error "HSI16 not enabled, required by STM32_STOPWUCK" -#endif - -#endif /* !STM32_HSI16_ENABLED */ - -#if STM32_CLOCK_HAS_HSI48 -#if STM32_HSI48_ENABLED -#else /* !STM32_HSI48_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_HSI48 -#error "HSI48 not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 -#error "HSI48 not enabled, required by STM32_CLK48SEL" -#endif -#endif /* !STM32_HSI48_ENABLED */ -#endif /* STM32_CLOCK_HAS_HSI48 */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - - #if STM32_HSECLK == 0 - #error "HSE frequency not defined" - #else /* STM32_HSECLK != 0 */ - #if defined(STM32_HSE_BYPASS) - #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" - #endif - #else /* !defined(STM32_HSE_BYPASS) */ - #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" - #endif - #endif /* !defined(STM32_HSE_BYPASS) */ - #endif /* STM32_HSECLK != 0 */ - - #else /* !STM32_HSE_ENABLED */ - - #if STM32_SW == STM32_SW_HSE - #error "HSE not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) - #error "HSE not enabled, required by STM32_MCOSEL" - #endif - - #if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) | \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SAI1SEL" - #endif - - #if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) | \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SAI2SEL" - #endif - - #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV - #error "HSE not enabled, required by STM32_RTCSEL" - #endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - - #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) - #error "LSI not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSI - #error "LSI not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSI - #error "LSI not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - - #if (STM32_LSECLK == 0) - #error "LSE frequency not defined" - #endif - - #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) - #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" - #endif - -#else /* !STM32_LSE_ENABLED */ - - #if STM32_RTCSEL == STM32_RTCSEL_LSE - #error "LSE not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSE - #error "LSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSE - #error "LSE not enabled, required by STM32_LSCOSEL" - #endif - - #if STM32_MSIPLL_ENABLED == TRUE - #error "LSE not enabled, required by STM32_MSIPLL_ENABLED" - #endif - -#endif /* !STM32_LSE_ENABLED */ - -/* - * MSI related checks. - */ -#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED -#warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED" -#endif - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 8)) || \ - defined(__DOXYGEN__) -#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) -#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_MSI -#define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 -#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK -#define STM32_PLLCLKIN 0 - -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLLs input frequency range check. - */ -#if (STM32_PLLCLKIN != 0) && \ - ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ - defined(__DOXYGEN__) - -#if STM32_PLLCLKIN == 0 -#error "PLL activation required but no PLL clock selected" -#endif - -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 86)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 8) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLP (0 << 17) - -#elif STM32_PLLP_VALUE == 17 -#define STM32_PLLP (1 << 17) - -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLQ (0 << 21) - -#elif STM32_PLLQ_VALUE == 4 -#define STM32_PLLQ (1 << 21) - -#elif STM32_PLLQ_VALUE == 6 -#define STM32_PLLQ (2 << 21) - -#elif STM32_PLLQ_VALUE == 8 -#define STM32_PLLQ (3 << 21) - -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLR field. - */ -#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLR (0 << 25) - -#elif STM32_PLLR_VALUE == 4 -#define STM32_PLLR (1 << 25) - -#elif STM32_PLLR_VALUE == 6 -#define STM32_PLLR (2 << 25) - -#elif STM32_PLLR_VALUE == 8 -#define STM32_PLLR (3 << 25) - -#else -#error "invalid STM32_PLLR_VALUE value specified" -#endif - -#if defined(STM32L496xx) || defined(STM32L4A6xx) -/** - * @brief STM32_PLLPDIV field. (Only for STM32L496xx/4A6xx) - */ -#if (STM32_PLLPDIV_VALUE == 0) || \ - ((STM32_PLLPDIV_VALUE >= 2) && (STM32_PLLPDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) -#else -#error "invalid STM32_PLLPDIV_VALUE value specified" -#endif -#endif - -/** - * @brief STM32_PLLPEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ - defined(__DOXYGEN__) -#define STM32_PLLPEN (1 << 16) -#else -#define STM32_PLLPEN (0 << 16) -#endif - -/** - * @brief STM32_PLLQEN field. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__) -#define STM32_PLLQEN (1 << 20) -#else -#define STM32_PLLQEN (0 << 20) -#endif - -/** - * @brief STM32_PLLREN field. - */ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - defined(__DOXYGEN__) -#define STM32_PLLREN (1 << 24) -#else -#define STM32_PLLREN (0 << 24) -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL P output clock frequency. - */ -#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) -#else -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) -#endif - -/** - * @brief PLL Q output clock frequency. - */ -#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) - -/** - * @brief PLL R output clock frequency. - */ -#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) - -/* - * PLL-P output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLL-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLL-R output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_MSICLK - -#elif (STM32_SW == STM32_SW_MSI) -#define STM32_SYSCLK STM32_MSICLK - -#elif (STM32_SW == STM32_SW_HSI16) -#define STM32_SYSCLK STM32_HSI16CLK - -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK - -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLL_R_CLKOUT - -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) - -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) - -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) - -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) - -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) - -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) - -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) - -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) - -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) - -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/* - * PLLSAI1 enable check. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \ - (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ - defined(__DOXYGEN__) - -#if STM32_PLLCLKIN == 0 -#error "PLLSAI1 activation required but no PLL clock selected" -#endif - -/** - * @brief PLLSAI1 activation flag. - */ -#define STM32_ACTIVATE_PLLSAI1 TRUE -#else -#define STM32_ACTIVATE_PLLSAI1 FALSE -#endif - -/** - * @brief STM32_PLLSAI1N field. - */ -#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 86)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8) -#else -#error "invalid STM32_PLLSAI1N_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1P field. - */ -#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLSAI1P (0 << 17) - -#elif STM32_PLLSAI1P_VALUE == 17 -#define STM32_PLLSAI1P (1 << 17) - -#else -#error "invalid STM32_PLLSAI1P_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1Q field. - */ -#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI1Q (0 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 4 -#define STM32_PLLSAI1Q (1 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 6 -#define STM32_PLLSAI1Q (2 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 8 -#define STM32_PLLSAI1Q (3 << 21) - -#else -#error "invalid STM32_PLLSAI1Q_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1R field. - */ -#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI1R (0 << 25) - -#elif STM32_PLLSAI1R_VALUE == 4 -#define STM32_PLLSAI1R (1 << 25) - -#elif STM32_PLLSAI1R_VALUE == 6 -#define STM32_PLLSAI1R (2 << 25) - -#elif STM32_PLLSAI1R_VALUE == 8 -#define STM32_PLLSAI1R (3 << 25) - -#else -#error "invalid STM32_PLLSAI1R_VALUE value specified" -#endif - -#if defined(STM32L496xx) || defined(STM32L4A6xx) -/** - * @brief STM32_PLLSAI1PDIV field. (Only for STM32L496xx/4A6xx) - */ -#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27) -#else -#error "invalid STM32_PLLSAI1PDIV_VALUE value specified" -#endif -#endif - -/** - * @brief STM32_PLLSAI1PEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1PEN (1 << 16) -#else -#define STM32_PLLSAI1PEN (0 << 16) -#endif - -/** - * @brief STM32_PLLSAI1QEN field. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_PLLSAI1QEN (1 << 20) -#else -#define STM32_PLLSAI1QEN (0 << 20) -#endif - -/** - * @brief STM32_PLLSAI1REN field. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_PLLSAI1REN (1 << 24) -#else -#define STM32_PLLSAI1REN (0 << 24) -#endif - -/** - * @brief PLLSAI1 VCO frequency. - */ -#define STM32_PLLSAI1VCO (STM32_PLLCLKIN * STM32_PLLSAI1N_VALUE) - -/* - * PLLSAI1 VCO frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI1-P output clock frequency. - */ -#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE) -#else -#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE) -#endif - -/** - * @brief PLLSAI1-Q output clock frequency. - */ -#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) - -/** - * @brief PLLSAI1-R output clock frequency. - */ -#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE) - -/* - * PLLSAI1-P output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLLSAI1-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLLSAI1-R output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/* - * PLLSAI2 enable check. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ - (STM32_ADCSEL == STM32_ADCSEL_PLLSAI2) || \ - defined(__DOXYGEN__) - -#if STM32_PLLCLKIN == 0 -#error "PLLSAI2 activation required but no PLL clock selected" -#endif - -/** - * @brief PLLSAI2 activation flag. - */ -#define STM32_ACTIVATE_PLLSAI2 TRUE -#else -#define STM32_ACTIVATE_PLLSAI2 FALSE -#endif - -/** - * @brief STM32_PLLSAI2N field. - */ -#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 86)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8) -#else -#error "invalid STM32_PLLSAI2N_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2P field. - */ -#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLSAI2P (0 << 17) - -#elif STM32_PLLSAI2P_VALUE == 17 -#define STM32_PLLSAI2P (1 << 17) - -#else -#error "invalid STM32_PLLSAI2P_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2R field. - */ -#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI2R (0 << 25) - -#elif STM32_PLLSAI2R_VALUE == 4 -#define STM32_PLLSAI2R (1 << 25) - -#elif STM32_PLLSAI2R_VALUE == 6 -#define STM32_PLLSAI2R (2 << 25) - -#elif STM32_PLLSAI2R_VALUE == 8 -#define STM32_PLLSAI2R (3 << 25) - -#else -#error "invalid STM32_PLLSAI2R_VALUE value specified" -#endif - -#if defined(STM32L496xx) || defined(STM32L4A6xx) -/** - * @brief STM32_PLLSAI2PDIV field. (Only for STM32L496xx/4A6xx) - */ -#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27) -#else -#error "invalid STM32_PLLSAI2PDIV_VALUE value specified" -#endif -#endif - -/** - * @brief STM32_PLLSAI2PEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2PEN (1 << 16) -#else -#define STM32_PLLSAI2PEN (0 << 16) -#endif - -/** - * @brief STM32_PLLSAI2REN field. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI2) || defined(__DOXYGEN__) -#define STM32_PLLSAI2REN (1 << 24) -#else -#define STM32_PLLSAI2REN (0 << 24) -#endif - -/** - * @brief PLLSAI2 VCO frequency. - */ -#define STM32_PLLSAI2VCO (STM32_PLLCLKIN * STM32_PLLSAI2N_VALUE) - -/* - * PLLSAI2 VCO frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI2-P output clock frequency. - */ -#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE) -#else -#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE) -#endif - -/** - * @brief PLLSAI2-R output clock frequency. - */ -#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE) - -/* - * PLLSAI2-P output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLLSAI2-R output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief MCO divider clock frequency. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 - -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK -#define STM32_MCODIVCLK STM32_SYSCLK - -#elif STM32_MCOSEL == STM32_MCOSEL_MSI -#define STM32_MCODIVCLK STM32_MSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 -#define STM32_MCODIVCLK STM32_HSI16CLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_PLL -#define STM32_MCODIVCLK STM32_PLL_R_CLKOUT - -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 -#define STM32_MCODIVCLK STM32_HSI48CLK - -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock frequency. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) - -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief RTC clock frequency. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 clock frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK2 -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 -#define STM32_USART1CLK STM32_HSI16CLK -#elif STM32_USART1SEL == STM32_USART1SEL_LSE -#define STM32_USART1CLK STM32_LSECLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 clock frequency. - */ -#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK1 -#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 -#define STM32_USART2CLK STM32_HSI16CLK -#elif STM32_USART2SEL == STM32_USART2SEL_LSE -#define STM32_USART2CLK STM32_LSECLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 clock frequency. - */ -#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART3CLK STM32_PCLK1 -#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK -#elif STM32_USART3SEL == STM32_USART3SEL_HSI16 -#define STM32_USART3CLK STM32_HSI16CLK -#elif STM32_USART3SEL == STM32_USART3SEL_LSE -#define STM32_USART3CLK STM32_LSECLK -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief UART4 clock frequency. - */ -#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART4CLK STM32_PCLK1 -#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK -#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 -#define STM32_UART4CLK STM32_HSI16CLK -#elif STM32_UART4SEL == STM32_UART4SEL_LSE -#define STM32_UART4CLK STM32_LSECLK -#else -#error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 clock frequency. - */ -#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART5CLK STM32_PCLK1 -#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK -#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 -#define STM32_UART5CLK STM32_HSI16CLK -#elif STM32_UART5SEL == STM32_UART5SEL_LSE -#define STM32_UART5CLK STM32_LSECLK -#else -#error "invalid source selected for UART5 clock" -#endif - -/** - * @brief LPUART1 clock frequency. - */ -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPUART1CLK STM32_PCLK1 -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK -#define STM32_LPUART1CLK STM32_SYSCLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 -#define STM32_LPUART1CLK STM32_HSI16CLK -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE -#define STM32_LPUART1CLK STM32_LSECLK -#else -#error "invalid source selected for LPUART1 clock" -#endif - -/** - * @brief I2C1 clock frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK1 -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 -#define STM32_I2C1CLK STM32_HSI16CLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 clock frequency. - */ -#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C2CLK STM32_PCLK1 -#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK -#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 -#define STM32_I2C2CLK STM32_HSI16CLK -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief I2C3 clock frequency. - */ -#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C3CLK STM32_PCLK1 -#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK -#define STM32_I2C3CLK STM32_SYSCLK -#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 -#define STM32_I2C3CLK STM32_HSI16CLK -#else -#error "invalid source selected for I2C3 clock" -#endif - -/** - * @brief I2C4 clock frequency. - */ -#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C4CLK STM32_PCLK1 -#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK -#define STM32_I2C4CLK STM32_SYSCLK -#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 -#define STM32_I2C4CLK STM32_HSI16CLK -#else -#error "invalid source selected for I2C4 clock" -#endif - -/** - * @brief LPTIM1 clock frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK1 -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI -#define STM32_LPTIM1CLK STM32_LSICLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 -#define STM32_LPTIM1CLK STM32_HSI16CLK -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE -#define STM32_LPTIM1CLK STM32_LSECLK -#else -#error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief LPTIM2 clock frequency. - */ -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM2CLK STM32_PCLK1 -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI -#define STM32_LPTIM2CLK STM32_LSICLK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 -#define STM32_LPTIM2CLK STM32_HSI16CLK -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE -#define STM32_LPTIM2CLK STM32_LSECLK -#else -#error "invalid source selected for LPTIM2 clock" -#endif - -/** - * @brief 48MHz clock frequency. - */ -#if !STM32_CLOCK_HAS_HSI48 || defined(__DOXYGEN__) - -#if (STM32_CLK48SEL == STM32_CLK48SEL_NOCLK) || defined(__DOXYGEN__) -#define STM32_48CLK 0 -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 -#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL -#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) -#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI -#define STM32_48CLK STM32_MSICLK -#else -#error "invalid source selected for 48CLK clock" -#endif - -#else /* STM32_CLOCK_HAS_HSI48 */ - -#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) -#define STM32_48CLK STM32_HSI48CLK -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 -#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL -#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) -#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI -#define STM32_48CLK STM32_MSICLK -#else -#error "invalid source selected for 48CLK clock" -#endif - -#endif /* STM32_CLOCK_HAS_HSI48 */ - -/** - * @brief SAI1 clock frequency. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2 -#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL -#define STM32_SAI1CLK STM32_PLL_P_CLKOUT -#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK -#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ -#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF -#define STM32_SAI1CLK 0 -#else -#error "invalid source selected for SAI1 clock" -#endif - -/** - * @brief SAI2 clock frequency. - */ -#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT -#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2 -#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT -#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL -#define STM32_SAI2CLK STM32_PLL_P_CLKOUT -#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK -#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ -#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF -#define STM32_SAI2CLK 0 -#else -#error "invalid source selected for SAI2 clock" -#endif - -/** - * @brief USB clock point. - */ -#define STM32_USBCLK STM32_48CLK - -/** - * @brief RNG clock point. - */ -#define STM32_RNGCLK STM32_48CLK - -/** - * @brief ADC clock frequency. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__) -#define STM32_ADCCLK 0 -#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1 -#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT -#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI2 -#define STM32_ADCCLK STM32_PLLSAI2_R_CLKOUT -#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK -#define STM32_ADCCLK STM32_SYSCLK -#else -#error "invalid source selected for ADC clock" -#endif - -/** - * @brief SWPMI1 clock frequency. - */ -#if (STM32_SWPMI1SEL == STM32_SWPMI1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_SWPMI1CLK STM32_PCLK1 -#elif STM32_SWPMI1SEL == STM32_SWPMI1SEL_HSI16 -#define STM32_SWPMI1CLK STM32_HSI16CLK -#else -#error "invalid source selected for SWPMI1 clock" -#endif - -/** - * @brief DFSDM clock frequency. - */ -#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_DFSDMCLK STM32_PCLK2 -#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK -#define STM32_DFSDMCLK STM32_SYSCLK -#else -#error "invalid source selected for DFSDM clock" -#endif - -/** - * @brief SDMMC frequency. - */ -#define STM32_SDMMC1CLK STM32_48CLK - -/** - * @brief Clock of timers connected to APB1 - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Clock of timers connected to APB2. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS - -#else -#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS -#endif - -/** - * @brief Flash settings for MSI. - */ -#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_MSICLK <= STM32_1WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_MSICLK <= STM32_2WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_MSICLK <= STM32_3WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS - -#else -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx/hal_lld.h + * @brief STM32L4xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32L432xx, STM32L433xx, STM32L443xx. + * - STM32L471xx, STM32L475xx, STM32L476xx, STM32L496xx. + * - STM32L485xx, STM32L486xx, STM32L4A6xx. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L471xx) || defined(STM32L475xx) || \ + defined(STM32L476xx) || defined(STM32L496xx) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32L4xx Ultra Low Power" + +#elif defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L4A6xx) +#define PLATFORM_NAME "STM32L4xx Ultra Low Power with Crypto" + +#else +#error "STM32L4xx device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32L4XX) || defined(__DOXYGEN__) +#define STM32L4XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ +#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR1 register bits definitions + * @{ + */ +#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */ +#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */ +#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ +/** @} */ + +/** + * @name PWR_CR2 register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ +#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CR register bits definitions + * @{ + */ +#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */ +#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */ +#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */ +#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */ +#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */ +#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */ +#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */ +#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */ +#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */ +#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */ +#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */ +#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */ +#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ +#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ +#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */ +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */ +#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */ +#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */ + +#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ +#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ + +#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ +#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ +#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ +#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ +#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ +#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */ +#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CCIPR register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ +#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ +#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ +#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */ +#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ + +#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ +#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ +#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ +#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */ +#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ + +#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ +#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ +#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ +#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */ +#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ + +#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ +#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ +#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ +#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */ +#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ + +#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ +#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ +#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ +#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */ +#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ + +#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */ +#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */ +#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */ +#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */ +#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */ + +#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */ +#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */ + +#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */ +#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */ +#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */ +#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */ + +#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */ +#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */ +#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */ +#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */ + +#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */ +#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */ +#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */ +#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */ + +#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */ +#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */ +#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */ +#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */ +#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */ + +#define STM32_SAI1SEL_MASK (3 << 22) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_PLLSAI1 (0 << 22) /**< SAI1 source is PLLSAI1-P. */ +#define STM32_SAI1SEL_PLLSAI2 (1 << 22) /**< SAI1 source is PLLSAI2-P. */ +#define STM32_SAI1SEL_PLL (2 << 22) /**< SAI1 source is PLL-P. */ +#define STM32_SAI1SEL_EXTCLK (3 << 22) /**< SAI1 source is external. */ +#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ + +#define STM32_SAI2SEL_MASK (3 << 24) /**< SAI2SEL mask. */ +#define STM32_SAI2SEL_PLLSAI1 (0 << 24) /**< SAI2 source is PLLSAI1-P. */ +#define STM32_SAI2SEL_PLLSAI2 (1 << 24) /**< SAI2 source is PLLSAI2-P. */ +#define STM32_SAI2SEL_PLL (2 << 24) /**< SAI2 source is PLL-P. */ +#define STM32_SAI2SEL_EXTCLK (3 << 24) /**< SAI2 source is external. */ +#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ + +#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */ +#if !STM32_CLOCK_HAS_HSI48 +#define STM32_CLK48SEL_NOCLK (0 << 26) /**< CLK48 disabled. */ +#else +#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */ +#endif +#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */ +#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */ +#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */ + +#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */ +#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */ +#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */ +#define STM32_ADCSEL_PLLSAI2 (2 << 28) /**< ADC source is PLLSAI2-R. */ +#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */ + +#define STM32_SWPMI1SEL_MASK (1 << 30) /**< SWPMI1SEL mask. */ +#define STM32_SWPMI1SEL_PCLK1 (0 << 30) /**< SWPMI1 source is PCLK1. */ +#define STM32_SWPMI1SEL_HSI16 (1 << 30) /**< SWPMI1 source is HSI16. */ + +#define STM32_DFSDMSEL_MASK (1 << 31) /**< DFSDMSEL mask. */ +#define STM32_DFSDMSEL_PCLK2 (0 << 31) /**< DFSDM source is PCLK2. */ +#define STM32_DFSDMSEL_SYSCLK (1 << 31) /**< DFSDM source is SYSCLK. */ +/** @} */ + +/** + * @name RCC_CCIPR2 register bits definitions + * @{ + */ +#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */ +#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */ +#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */ +/** @} */ + +/** + * @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. */ + +#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */ +#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */ +#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */ +#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */ +/** @} */ + +/** + * @name RCC_CSR register bits definitions + * @{ + */ +#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */ +#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */ +#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */ +#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */ +#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_RANGE1 +#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 HSI16 clock source. + */ +#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSI48 clock source. + */ +#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI48_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief Enables or disables the MSI PLL on LSE clock source. + */ +#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__) +#define STM32_MSIPLL_ENABLED FALSE +#endif + +/** + * @brief MSI frequency setting. + */ +#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) +#define STM32_MSIRANGE STM32_MSIRANGE_4M +#endif + +/** + * @brief MSI frequency setting after standby. + */ +#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__) +#define STM32_MSISRANGE STM32_MSISRANGE_4M +#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 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_MSI +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 1..8. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 1 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 8..86. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 80 +#endif + +/** + * @brief PLLPDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLPDIV_VALUE 0 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 7, 17. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 7 +#endif + +/** + * @brief PLLQ divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 6 +#endif + +/** + * @brief PLLR divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLR_VALUE 4 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 80MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief STOPWUCK clock setting. + */ +#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) +#define STM32_STOPWUCK STM32_STOPWUCK_MSI +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief LSCO clock source. + */ +#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#endif + +/** + * @brief PLLSAI1N multiplier value. + * @note The allowed values are 8..86. + */ +#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1N_VALUE 80 +#endif + +/** + * @brief PLLSAI1PDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1PDIV_VALUE 0 +#endif + +/** + * @brief PLLSAI1P divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1P_VALUE 7 +#endif + +/** + * @brief PLLSAI1Q divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1Q_VALUE 6 +#endif + +/** + * @brief PLLSAI1R divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1R_VALUE 4 +#endif + +/** + * @brief PLLSAI2N multiplier value. + * @note The allowed values are 8..86. + */ +#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2N_VALUE 80 +#endif + +/** + * @brief PLLSAI2PDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2PDIV_VALUE 0 +#endif + +/** + * @brief PLLSAI2P divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2P_VALUE 7 +#endif + +/** + * @brief PLLSAI2R divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2R_VALUE 4 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) +#define STM32_UART5SEL STM32_UART5SEL_SYSCLK +#endif + +/** + * @brief LPUART1 clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) +#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK +#endif + +/** + * @brief I2C3 clock source. + */ +#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) +#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK +#endif + +/** + * @brief I2C4 clock source. + */ +#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) +#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#endif + +/** + * @brief LPTIM2 clock source. + */ +#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 +#endif + +/** + * @brief SAI1SEL value (SAI1 clock source). + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#endif + +/** + * @brief SAI2SEL value (SAI2 clock source). + */ +#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#endif + +/** + * @brief CLK48SEL value (48MHz clock source). + */ +#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) +#define STM32_CLK48SEL STM32_CLK48SEL_PLL +#endif + +/** + * @brief ADCSEL value (ADCs clock source). + */ +#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) +#define STM32_ADCSEL STM32_ADCSEL_SYSCLK +#endif + +/** + * @brief SWPMI1SEL value (SWPMI clock source). + */ +#if !defined(STM32_SWPMI1SEL) || defined(__DOXYGEN__) +#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 +#endif + +/** + * @brief DFSDMSEL value (DFSDM clock source). + */ +#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__) +#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 +#endif + +/** + * @brief RTC/LCD clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32L4xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4xx_MCUCONF not defined" +#endif + +/* Only some devices have strongly checked mcuconf.h files. Others will be + added gradually.*/ +#if defined(STM32L432xx) && !defined(STM32L432_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L432_MCUCONF not defined" +#endif + +#if defined(STM32L433xx) && !defined(STM32L433_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L433_MCUCONF not defined" +#endif + +#if defined(STM32L476xx) && !defined(STM32L476_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L476_MCUCONF not defined" +#endif + +#if defined(STM32L486xx) && !defined(STM32L486_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L486_MCUCONF not defined" +#endif + +#if defined(STM32L496xx) && !defined(STM32L496_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L496_MCUCONF not defined" +#endif + +#if defined(STM32L4A6xx) && !defined(STM32L4A6_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L4A6_MCUCONF not defined" +#endif + +/* + * Board files sanity checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif + +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__) +/** + * @name System Limits + * @{ + */ +/** + * @brief Maximum SYSCLK clock frequency at current voltage setting. + */ +#define STM32_SYSCLK_MAX 80000000 + +/** + * @brief Maximum HSE clock frequency at current voltage setting. + */ +#define STM32_HSECLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 48000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MIN 8000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 16000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 4000000 + +/** + * @brief Maximum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MAX 344000000 + +/** + * @brief Minimum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MIN 64000000 + +/** + * @brief Maximum PLL-P output clock frequency. + */ +#define STM32_PLLP_MAX 80000000 + +/** + * @brief Minimum PLL-P output clock frequency. + */ +#define STM32_PLLP_MIN 2064500 + +/** + * @brief Maximum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MAX 80000000 + +/** + * @brief Minimum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MIN 8000000 + +/** + * @brief Maximum PLL-R output clock frequency. + */ +#define STM32_PLLR_MAX 80000000 + +/** + * @brief Minimum PLL-R output clock frequency. + */ +#define STM32_PLLR_MIN 8000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 80000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 80000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 80000000 +/** @} */ + +/** + * @name Flash Wait states + * @{ + */ +#define STM32_0WS_THRESHOLD 16000000 +#define STM32_1WS_THRESHOLD 32000000 +#define STM32_2WS_THRESHOLD 48000000 +#define STM32_3WS_THRESHOLD 64000000 +/** @} */ + +#elif STM32_VOS == STM32_VOS_RANGE2 +#define STM32_SYSCLK_MAX 26000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 26000000 +#define STM32_HSECLK_MIN 8000000 +#define STM32_HSECLK_BYP_MIN 8000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_LSECLK_BYP_MIN 32768 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MIN 4000000 +#define STM32_PLLVCO_MAX 128000000 +#define STM32_PLLVCO_MIN 64000000 +#define STM32_PLLP_MAX 26000000 +#define STM32_PLLP_MIN 2064500 +#define STM32_PLLQ_MAX 26000000 +#define STM32_PLLQ_MIN 8000000 +#define STM32_PLLR_MAX 26000000 +#define STM32_PLLR_MIN 8000000 +#define STM32_PCLK1_MAX 26000000 +#define STM32_PCLK2_MAX 26000000 +#define STM32_ADCCLK_MAX 26000000 + +#define STM32_0WS_THRESHOLD 6000000 +#define STM32_1WS_THRESHOLD 12000000 +#define STM32_2WS_THRESHOLD 18000000 +#define STM32_3WS_THRESHOLD 26000000 + +#else +#error "invalid STM32_VOS value specified" +#endif + +/** + * @brief MSI frequency. + */ +#if STM32_MSIRANGE == STM32_MSIRANGE_100K +#define STM32_MSICLK 100000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_200K +#define STM32_MSICLK 200000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_400K +#define STM32_MSICLK 400000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_800K +#define STM32_MSICLK 800000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_1M +#define STM32_MSICLK 1000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_2M +#define STM32_MSICLK 2000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_4M +#define STM32_MSICLK 4000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_8M +#define STM32_MSICLK 8000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_16M +#define STM32_MSICLK 16000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_24M +#define STM32_MSICLK 24000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_32M +#define STM32_MSICLK 32000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_48M +#define STM32_MSICLK 48000000 +#else +#error "invalid STM32_MSIRANGE value specified" +#endif + +/** + * @brief MSIS frequency. + */ +#if STM32_MSISRANGE == STM32_MSISRANGE_1M +#define STM32_MSISCLK 1000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_2M +#define STM32_MSISCLK 2000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_4M +#define STM32_MSISCLK 4000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_8M +#define STM32_MSISCLK 8000000 +#else +#error "invalid STM32_MSISRANGE value specified" +#endif + +/* + * HSI16 related checks. + */ +#if STM32_HSI16_ENABLED +#else /* !STM32_HSI16_ENABLED */ + +#if STM32_SW == STM32_SW_HSI16 +#error "HSI16 not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16)) +#error "HSI16 not enabled, required by STM32_MCOSEL" +#endif + +#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SAI1SEL" +#endif + +#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16) +#error "HSI16 not enabled, required by STM32_SAI2SEL" +#endif + +#if (STM32_USART1SEL == STM32_USART1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART1SEL" +#endif +#if (STM32_USART2SEL == STM32_USART2SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART2SEL" +#endif +#if (STM32_USART3SEL == STM32_USART3SEL_HSI16) +#error "HSI16 not enabled, required by STM32_USART3SEL" +#endif +#if (STM32_UART4SEL == STM32_UART4SEL_HSI16) +#error "HSI16 not enabled, required by STM32_UART4SEL" +#endif +#if (STM32_UART5SEL == STM32_UART5SEL_HSI16) +#error "HSI16 not enabled, required by STM32_UART5SEL" +#endif +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) +#error "HSI16 not enabled, required by STM32_LPUART1SEL" +#endif + +#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) +#error "HSI16 not enabled, required by I2C1SEL" +#endif +#if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) +#error "HSI16 not enabled, required by I2C2SEL" +#endif +#if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) +#error "HSI16 not enabled, required by I2C3SEL" +#endif +#if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) +#error "HSI16 not enabled, required by I2C4SEL" +#endif + +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) +#error "HSI16 not enabled, required by LPTIM1SEL" +#endif +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) +#error "HSI16 not enabled, required by LPTIM2SEL" +#endif + +#if (STM32_SWPMI1SEL == STM32_SWPMI1SEL_HSI16) +#error "HSI16 not enabled, required by SWPMI1SEL" +#endif +#if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16) +#error "HSI16 not enabled, required by STM32_STOPWUCK" +#endif + +#endif /* !STM32_HSI16_ENABLED */ + +#if STM32_CLOCK_HAS_HSI48 +#if STM32_HSI48_ENABLED +#else /* !STM32_HSI48_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_HSI48 +#error "HSI48 not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 +#error "HSI48 not enabled, required by STM32_CLK48SEL" +#endif +#endif /* !STM32_HSI48_ENABLED */ +#endif /* STM32_CLOCK_HAS_HSI48 */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + + #if STM32_HSECLK == 0 + #error "HSE frequency not defined" + #else /* STM32_HSECLK != 0 */ + #if defined(STM32_HSE_BYPASS) + #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" + #endif + #else /* !defined(STM32_HSE_BYPASS) */ + #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" + #endif + #endif /* !defined(STM32_HSE_BYPASS) */ + #endif /* STM32_HSECLK != 0 */ + + #else /* !STM32_HSE_ENABLED */ + + #if STM32_SW == STM32_SW_HSE + #error "HSE not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) + #error "HSE not enabled, required by STM32_MCOSEL" + #endif + + #if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) | \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SAI1SEL" + #endif + + #if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) | \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SAI2SEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV + #error "HSE not enabled, required by STM32_RTCSEL" + #endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + + #if HAL_USE_RTC && (STM32_RTCSEL == STM32_RTCSEL_LSI) + #error "LSI not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSI + #error "LSI not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSI + #error "LSI not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + + #if (STM32_LSECLK == 0) + #error "LSE frequency not defined" + #endif + + #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) + #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" + #endif + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) + #error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" + #endif + +#else /* !STM32_LSE_ENABLED */ + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) + #error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_LSE + #error "LSE not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSE + #error "LSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSE + #error "LSE not enabled, required by STM32_LSCOSEL" + #endif + + #if STM32_MSIPLL_ENABLED == TRUE + #error "LSE not enabled, required by STM32_MSIPLL_ENABLED" + #endif + +#endif /* !STM32_LSE_ENABLED */ + +/* + * MSI related checks. + */ +#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED +#warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED" +#endif + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 8)) || \ + defined(__DOXYGEN__) +#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) +#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_MSI +#define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 +#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK +#define STM32_PLLCLKIN 0 + +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLLs input frequency range check. + */ +#if (STM32_PLLCLKIN != 0) && \ + ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ + defined(__DOXYGEN__) + +#if STM32_PLLCLKIN == 0 +#error "PLL activation required but no PLL clock selected" +#endif + +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 86)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 8) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLP (0 << 17) + +#elif STM32_PLLP_VALUE == 17 +#define STM32_PLLP (1 << 17) + +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLQ (0 << 21) + +#elif STM32_PLLQ_VALUE == 4 +#define STM32_PLLQ (1 << 21) + +#elif STM32_PLLQ_VALUE == 6 +#define STM32_PLLQ (2 << 21) + +#elif STM32_PLLQ_VALUE == 8 +#define STM32_PLLQ (3 << 21) + +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLR field. + */ +#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLR (0 << 25) + +#elif STM32_PLLR_VALUE == 4 +#define STM32_PLLR (1 << 25) + +#elif STM32_PLLR_VALUE == 6 +#define STM32_PLLR (2 << 25) + +#elif STM32_PLLR_VALUE == 8 +#define STM32_PLLR (3 << 25) + +#else +#error "invalid STM32_PLLR_VALUE value specified" +#endif + +#if defined(STM32L496xx) || defined(STM32L4A6xx) +/** + * @brief STM32_PLLPDIV field. (Only for STM32L496xx/4A6xx) + */ +#if (STM32_PLLPDIV_VALUE == 0) || \ + ((STM32_PLLPDIV_VALUE >= 2) && (STM32_PLLPDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) +#else +#error "invalid STM32_PLLPDIV_VALUE value specified" +#endif +#endif + +/** + * @brief STM32_PLLPEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ + defined(__DOXYGEN__) +#define STM32_PLLPEN (1 << 16) +#else +#define STM32_PLLPEN (0 << 16) +#endif + +/** + * @brief STM32_PLLQEN field. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__) +#define STM32_PLLQEN (1 << 20) +#else +#define STM32_PLLQEN (0 << 20) +#endif + +/** + * @brief STM32_PLLREN field. + */ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + defined(__DOXYGEN__) +#define STM32_PLLREN (1 << 24) +#else +#define STM32_PLLREN (0 << 24) +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL P output clock frequency. + */ +#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) +#else +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) +#endif + +/** + * @brief PLL Q output clock frequency. + */ +#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) + +/** + * @brief PLL R output clock frequency. + */ +#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) + +/* + * PLL-P output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLL-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLL-R output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_MSICLK + +#elif (STM32_SW == STM32_SW_MSI) +#define STM32_SYSCLK STM32_MSICLK + +#elif (STM32_SW == STM32_SW_HSI16) +#define STM32_SYSCLK STM32_HSI16CLK + +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK + +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLL_R_CLKOUT + +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) + +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) + +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) + +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) + +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) + +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) + +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) + +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) + +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) + +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/* + * PLLSAI1 enable check. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \ + (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ + defined(__DOXYGEN__) + +#if STM32_PLLCLKIN == 0 +#error "PLLSAI1 activation required but no PLL clock selected" +#endif + +/** + * @brief PLLSAI1 activation flag. + */ +#define STM32_ACTIVATE_PLLSAI1 TRUE +#else +#define STM32_ACTIVATE_PLLSAI1 FALSE +#endif + +/** + * @brief STM32_PLLSAI1N field. + */ +#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 86)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8) +#else +#error "invalid STM32_PLLSAI1N_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1P field. + */ +#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLSAI1P (0 << 17) + +#elif STM32_PLLSAI1P_VALUE == 17 +#define STM32_PLLSAI1P (1 << 17) + +#else +#error "invalid STM32_PLLSAI1P_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1Q field. + */ +#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI1Q (0 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 4 +#define STM32_PLLSAI1Q (1 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 6 +#define STM32_PLLSAI1Q (2 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 8 +#define STM32_PLLSAI1Q (3 << 21) + +#else +#error "invalid STM32_PLLSAI1Q_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1R field. + */ +#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI1R (0 << 25) + +#elif STM32_PLLSAI1R_VALUE == 4 +#define STM32_PLLSAI1R (1 << 25) + +#elif STM32_PLLSAI1R_VALUE == 6 +#define STM32_PLLSAI1R (2 << 25) + +#elif STM32_PLLSAI1R_VALUE == 8 +#define STM32_PLLSAI1R (3 << 25) + +#else +#error "invalid STM32_PLLSAI1R_VALUE value specified" +#endif + +#if defined(STM32L496xx) || defined(STM32L4A6xx) +/** + * @brief STM32_PLLSAI1PDIV field. (Only for STM32L496xx/4A6xx) + */ +#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27) +#else +#error "invalid STM32_PLLSAI1PDIV_VALUE value specified" +#endif +#endif + +/** + * @brief STM32_PLLSAI1PEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1PEN (1 << 16) +#else +#define STM32_PLLSAI1PEN (0 << 16) +#endif + +/** + * @brief STM32_PLLSAI1QEN field. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_PLLSAI1QEN (1 << 20) +#else +#define STM32_PLLSAI1QEN (0 << 20) +#endif + +/** + * @brief STM32_PLLSAI1REN field. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_PLLSAI1REN (1 << 24) +#else +#define STM32_PLLSAI1REN (0 << 24) +#endif + +/** + * @brief PLLSAI1 VCO frequency. + */ +#define STM32_PLLSAI1VCO (STM32_PLLCLKIN * STM32_PLLSAI1N_VALUE) + +/* + * PLLSAI1 VCO frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI1-P output clock frequency. + */ +#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE) +#else +#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE) +#endif + +/** + * @brief PLLSAI1-Q output clock frequency. + */ +#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) + +/** + * @brief PLLSAI1-R output clock frequency. + */ +#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE) + +/* + * PLLSAI1-P output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLLSAI1-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLLSAI1-R output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/* + * PLLSAI2 enable check. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ + (STM32_ADCSEL == STM32_ADCSEL_PLLSAI2) || \ + defined(__DOXYGEN__) + +#if STM32_PLLCLKIN == 0 +#error "PLLSAI2 activation required but no PLL clock selected" +#endif + +/** + * @brief PLLSAI2 activation flag. + */ +#define STM32_ACTIVATE_PLLSAI2 TRUE +#else +#define STM32_ACTIVATE_PLLSAI2 FALSE +#endif + +/** + * @brief STM32_PLLSAI2N field. + */ +#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 86)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8) +#else +#error "invalid STM32_PLLSAI2N_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2P field. + */ +#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLSAI2P (0 << 17) + +#elif STM32_PLLSAI2P_VALUE == 17 +#define STM32_PLLSAI2P (1 << 17) + +#else +#error "invalid STM32_PLLSAI2P_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2R field. + */ +#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI2R (0 << 25) + +#elif STM32_PLLSAI2R_VALUE == 4 +#define STM32_PLLSAI2R (1 << 25) + +#elif STM32_PLLSAI2R_VALUE == 6 +#define STM32_PLLSAI2R (2 << 25) + +#elif STM32_PLLSAI2R_VALUE == 8 +#define STM32_PLLSAI2R (3 << 25) + +#else +#error "invalid STM32_PLLSAI2R_VALUE value specified" +#endif + +#if defined(STM32L496xx) || defined(STM32L4A6xx) +/** + * @brief STM32_PLLSAI2PDIV field. (Only for STM32L496xx/4A6xx) + */ +#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27) +#else +#error "invalid STM32_PLLSAI2PDIV_VALUE value specified" +#endif +#endif + +/** + * @brief STM32_PLLSAI2PEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2PEN (1 << 16) +#else +#define STM32_PLLSAI2PEN (0 << 16) +#endif + +/** + * @brief STM32_PLLSAI2REN field. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI2) || defined(__DOXYGEN__) +#define STM32_PLLSAI2REN (1 << 24) +#else +#define STM32_PLLSAI2REN (0 << 24) +#endif + +/** + * @brief PLLSAI2 VCO frequency. + */ +#define STM32_PLLSAI2VCO (STM32_PLLCLKIN * STM32_PLLSAI2N_VALUE) + +/* + * PLLSAI2 VCO frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI2-P output clock frequency. + */ +#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE) +#else +#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE) +#endif + +/** + * @brief PLLSAI2-R output clock frequency. + */ +#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE) + +/* + * PLLSAI2-P output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLLSAI2-R output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief MCO divider clock frequency. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 + +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK +#define STM32_MCODIVCLK STM32_SYSCLK + +#elif STM32_MCOSEL == STM32_MCOSEL_MSI +#define STM32_MCODIVCLK STM32_MSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 +#define STM32_MCODIVCLK STM32_HSI16CLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_PLL +#define STM32_MCODIVCLK STM32_PLL_R_CLKOUT + +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 +#define STM32_MCODIVCLK STM32_HSI48CLK + +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock frequency. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) + +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief RTC clock frequency. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 clock frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK2 +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 +#define STM32_USART1CLK STM32_HSI16CLK +#elif STM32_USART1SEL == STM32_USART1SEL_LSE +#define STM32_USART1CLK STM32_LSECLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 clock frequency. + */ +#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART2CLK STM32_PCLK1 +#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 +#define STM32_USART2CLK STM32_HSI16CLK +#elif STM32_USART2SEL == STM32_USART2SEL_LSE +#define STM32_USART2CLK STM32_LSECLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 clock frequency. + */ +#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART3CLK STM32_PCLK1 +#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK +#elif STM32_USART3SEL == STM32_USART3SEL_HSI16 +#define STM32_USART3CLK STM32_HSI16CLK +#elif STM32_USART3SEL == STM32_USART3SEL_LSE +#define STM32_USART3CLK STM32_LSECLK +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief UART4 clock frequency. + */ +#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART4CLK STM32_PCLK1 +#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK +#define STM32_UART4CLK STM32_SYSCLK +#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 +#define STM32_UART4CLK STM32_HSI16CLK +#elif STM32_UART4SEL == STM32_UART4SEL_LSE +#define STM32_UART4CLK STM32_LSECLK +#else +#error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 clock frequency. + */ +#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART5CLK STM32_PCLK1 +#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK +#define STM32_UART5CLK STM32_SYSCLK +#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 +#define STM32_UART5CLK STM32_HSI16CLK +#elif STM32_UART5SEL == STM32_UART5SEL_LSE +#define STM32_UART5CLK STM32_LSECLK +#else +#error "invalid source selected for UART5 clock" +#endif + +/** + * @brief LPUART1 clock frequency. + */ +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPUART1CLK STM32_PCLK1 +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK +#define STM32_LPUART1CLK STM32_SYSCLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 +#define STM32_LPUART1CLK STM32_HSI16CLK +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE +#define STM32_LPUART1CLK STM32_LSECLK +#else +#error "invalid source selected for LPUART1 clock" +#endif + +/** + * @brief I2C1 clock frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_PCLK1 +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 +#define STM32_I2C1CLK STM32_HSI16CLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 clock frequency. + */ +#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C2CLK STM32_PCLK1 +#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK +#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 +#define STM32_I2C2CLK STM32_HSI16CLK +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief I2C3 clock frequency. + */ +#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C3CLK STM32_PCLK1 +#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK +#define STM32_I2C3CLK STM32_SYSCLK +#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 +#define STM32_I2C3CLK STM32_HSI16CLK +#else +#error "invalid source selected for I2C3 clock" +#endif + +/** + * @brief I2C4 clock frequency. + */ +#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C4CLK STM32_PCLK1 +#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK +#define STM32_I2C4CLK STM32_SYSCLK +#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 +#define STM32_I2C4CLK STM32_HSI16CLK +#else +#error "invalid source selected for I2C4 clock" +#endif + +/** + * @brief LPTIM1 clock frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM1CLK STM32_PCLK1 +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI +#define STM32_LPTIM1CLK STM32_LSICLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 +#define STM32_LPTIM1CLK STM32_HSI16CLK +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE +#define STM32_LPTIM1CLK STM32_LSECLK +#else +#error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief LPTIM2 clock frequency. + */ +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM2CLK STM32_PCLK1 +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI +#define STM32_LPTIM2CLK STM32_LSICLK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 +#define STM32_LPTIM2CLK STM32_HSI16CLK +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE +#define STM32_LPTIM2CLK STM32_LSECLK +#else +#error "invalid source selected for LPTIM2 clock" +#endif + +/** + * @brief 48MHz clock frequency. + */ +#if !STM32_CLOCK_HAS_HSI48 || defined(__DOXYGEN__) + +#if (STM32_CLK48SEL == STM32_CLK48SEL_NOCLK) || defined(__DOXYGEN__) +#define STM32_48CLK 0 +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 +#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL +#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) +#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI +#define STM32_48CLK STM32_MSICLK +#else +#error "invalid source selected for 48CLK clock" +#endif + +#else /* STM32_CLOCK_HAS_HSI48 */ + +#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) +#define STM32_48CLK STM32_HSI48CLK +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 +#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL +#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) +#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI +#define STM32_48CLK STM32_MSICLK +#else +#error "invalid source selected for 48CLK clock" +#endif + +#endif /* STM32_CLOCK_HAS_HSI48 */ + +/** + * @brief SAI1 clock frequency. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2 +#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL +#define STM32_SAI1CLK STM32_PLL_P_CLKOUT +#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK +#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ +#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF +#define STM32_SAI1CLK 0 +#else +#error "invalid source selected for SAI1 clock" +#endif + +/** + * @brief SAI2 clock frequency. + */ +#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT +#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2 +#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT +#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL +#define STM32_SAI2CLK STM32_PLL_P_CLKOUT +#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK +#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ +#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF +#define STM32_SAI2CLK 0 +#else +#error "invalid source selected for SAI2 clock" +#endif + +/** + * @brief USB clock point. + */ +#define STM32_USBCLK STM32_48CLK + +/** + * @brief RNG clock point. + */ +#define STM32_RNGCLK STM32_48CLK + +/** + * @brief ADC clock frequency. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__) +#define STM32_ADCCLK 0 +#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1 +#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT +#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI2 +#define STM32_ADCCLK STM32_PLLSAI2_R_CLKOUT +#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK +#define STM32_ADCCLK STM32_SYSCLK +#else +#error "invalid source selected for ADC clock" +#endif + +/** + * @brief SWPMI1 clock frequency. + */ +#if (STM32_SWPMI1SEL == STM32_SWPMI1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_SWPMI1CLK STM32_PCLK1 +#elif STM32_SWPMI1SEL == STM32_SWPMI1SEL_HSI16 +#define STM32_SWPMI1CLK STM32_HSI16CLK +#else +#error "invalid source selected for SWPMI1 clock" +#endif + +/** + * @brief DFSDM clock frequency. + */ +#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_DFSDMCLK STM32_PCLK2 +#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK +#define STM32_DFSDMCLK STM32_SYSCLK +#else +#error "invalid source selected for DFSDM clock" +#endif + +/** + * @brief SDMMC frequency. + */ +#define STM32_SDMMC1CLK STM32_48CLK + +/** + * @brief Clock of timers connected to APB1 + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Clock of timers connected to APB2. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS + +#else +#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS +#endif + +/** + * @brief Flash settings for MSI. + */ +#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_MSICLK <= STM32_1WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_MSICLK <= STM32_2WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_MSICLK <= STM32_3WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS + +#else +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/platform.mk b/os/hal/ports/STM32/STM32L4xx/platform.mk index 5426ea32f6..9b1569ca94 100644 --- a/os/hal/ports/STM32/STM32L4xx/platform.mk +++ b/os/hal/ports/STM32/STM32L4xx/platform.mk @@ -1,49 +1,49 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_lld.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_lld.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32L4xx/platform_l432.mk b/os/hal/ports/STM32/STM32L4xx/platform_l432.mk index 960c70fa15..f3282c5e5d 100644 --- a/os/hal/ports/STM32/STM32L4xx/platform_l432.mk +++ b/os/hal/ports/STM32/STM32L4xx/platform_l432.mk @@ -1,48 +1,48 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_lld.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_lld.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32L4xx/stm32_isr.c b/os/hal/ports/STM32/STM32L4xx/stm32_isr.c index 291a6c2871..68ab519f9e 100644 --- a/os/hal/ports/STM32/STM32L4xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32L4xx/stm32_isr.c @@ -1,159 +1,159 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx/stm32_isr.c - * @brief STM32L4xx ISR handler code. - * - * @addtogroup STM32L4xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_exti0.inc" -#include "stm32_exti1.inc" -#include "stm32_exti2.inc" -#include "stm32_exti3.inc" -#include "stm32_exti4.inc" -#include "stm32_exti5_9.inc" -#include "stm32_exti10_15.inc" -#include "stm32_exti16-35_38.inc" -#include "stm32_exti18.inc" -#include "stm32_exti19.inc" -#include "stm32_exti20.inc" -#include "stm32_exti21_22.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart3.inc" -#include "stm32_uart4.inc" -#include "stm32_uart5.inc" -#include "stm32_lpuart1.inc" - -#include "stm32_tim1_15_16_17.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim4.inc" -#include "stm32_tim5.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim8.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_irq_init(); - exti1_irq_init(); - exti2_irq_init(); - exti3_irq_init(); - exti4_irq_init(); - exti5_9_irq_init(); - exti10_15_irq_init(); - exti16_exti35_38_irq_init(); - exti18_irq_init(); - exti19_irq_init(); - exti21_22_irq_init(); - - tim1_tim15_tim16_tim17_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim4_irq_init(); - tim5_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim8_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_irq_init(); - uart4_irq_init(); - uart5_irq_init(); - lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_irq_deinit(); - exti1_irq_deinit(); - exti2_irq_deinit(); - exti3_irq_deinit(); - exti4_irq_deinit(); - exti5_9_irq_deinit(); - exti10_15_irq_deinit(); - exti16_exti35_38_irq_deinit(); - exti18_irq_deinit(); - exti19_irq_deinit(); - exti21_22_irq_deinit(); - - tim1_tim15_tim16_tim17_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim4_irq_deinit(); - tim5_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim8_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_irq_deinit(); - uart4_irq_deinit(); - uart5_irq_deinit(); - lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx/stm32_isr.c + * @brief STM32L4xx ISR handler code. + * + * @addtogroup STM32L4xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_exti0.inc" +#include "stm32_exti1.inc" +#include "stm32_exti2.inc" +#include "stm32_exti3.inc" +#include "stm32_exti4.inc" +#include "stm32_exti5_9.inc" +#include "stm32_exti10_15.inc" +#include "stm32_exti16-35_38.inc" +#include "stm32_exti18.inc" +#include "stm32_exti19.inc" +#include "stm32_exti20.inc" +#include "stm32_exti21_22.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart3.inc" +#include "stm32_uart4.inc" +#include "stm32_uart5.inc" +#include "stm32_lpuart1.inc" + +#include "stm32_tim1_15_16_17.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim4.inc" +#include "stm32_tim5.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim8.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_irq_init(); + exti1_irq_init(); + exti2_irq_init(); + exti3_irq_init(); + exti4_irq_init(); + exti5_9_irq_init(); + exti10_15_irq_init(); + exti16_exti35_38_irq_init(); + exti18_irq_init(); + exti19_irq_init(); + exti21_22_irq_init(); + + tim1_tim15_tim16_tim17_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim4_irq_init(); + tim5_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim8_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_irq_init(); + uart4_irq_init(); + uart5_irq_init(); + lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_irq_deinit(); + exti1_irq_deinit(); + exti2_irq_deinit(); + exti3_irq_deinit(); + exti4_irq_deinit(); + exti5_9_irq_deinit(); + exti10_15_irq_deinit(); + exti16_exti35_38_irq_deinit(); + exti18_irq_deinit(); + exti19_irq_deinit(); + exti21_22_irq_deinit(); + + tim1_tim15_tim16_tim17_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim4_irq_deinit(); + tim5_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim8_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_irq_deinit(); + uart4_irq_deinit(); + uart5_irq_deinit(); + lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/stm32_isr.h b/os/hal/ports/STM32/STM32L4xx/stm32_isr.h index f4a629435f..9230352d91 100644 --- a/os/hal/ports/STM32/STM32L4xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32L4xx/stm32_isr.h @@ -1,289 +1,289 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx/stm32_isr.h - * @brief STM32L4xx ISR handler header. - * - * @addtogroup SRM32L4xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM8_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC unit. - */ -#define STM32_ADC1_HANDLER Vector88 -#define STM32_ADC2_HANDLER Vector88 -#define STM32_ADC3_HANDLER VectorFC - -#define STM32_ADC1_NUMBER 18 -#define STM32_ADC2_NUMBER 18 -#define STM32_ADC3_NUMBER 47 - -/* - * CAN unit. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 -#define STM32_CAN2_TX_HANDLER Vector198 -#define STM32_CAN2_RX0_HANDLER Vector19C -#define STM32_CAN2_RX1_HANDLER Vector1A0 -#define STM32_CAN2_SCE_HANDLER Vector1A4 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 -#define STM32_CAN2_TX_NUMBER 86 -#define STM32_CAN2_RX0_NUMBER 87 -#define STM32_CAN2_RX1_NUMBER 88 -#define STM32_CAN2_SCE_NUMBER 89 - -/* - * DMA unit. - */ -#define STM32_DMA1_CH1_HANDLER Vector6C -#define STM32_DMA1_CH2_HANDLER Vector70 -#define STM32_DMA1_CH3_HANDLER Vector74 -#define STM32_DMA1_CH4_HANDLER Vector78 -#define STM32_DMA1_CH5_HANDLER Vector7C -#define STM32_DMA1_CH6_HANDLER Vector80 -#define STM32_DMA1_CH7_HANDLER Vector84 -#define STM32_DMA2_CH1_HANDLER Vector120 -#define STM32_DMA2_CH2_HANDLER Vector124 -#define STM32_DMA2_CH3_HANDLER Vector128 -#define STM32_DMA2_CH4_HANDLER Vector12C -#define STM32_DMA2_CH5_HANDLER Vector130 -#define STM32_DMA2_CH6_HANDLER Vector150 -#define STM32_DMA2_CH7_HANDLER Vector154 - -#define STM32_DMA1_CH1_NUMBER 11 -#define STM32_DMA1_CH2_NUMBER 12 -#define STM32_DMA1_CH3_NUMBER 13 -#define STM32_DMA1_CH4_NUMBER 14 -#define STM32_DMA1_CH5_NUMBER 15 -#define STM32_DMA1_CH6_NUMBER 16 -#define STM32_DMA1_CH7_NUMBER 17 -#define STM32_DMA2_CH1_NUMBER 56 -#define STM32_DMA2_CH2_NUMBER 57 -#define STM32_DMA2_CH3_NUMBER 58 -#define STM32_DMA2_CH4_NUMBER 59 -#define STM32_DMA2_CH5_NUMBER 60 -#define STM32_DMA2_CH6_NUMBER 68 -#define STM32_DMA2_CH7_NUMBER 69 - -/* - * EXTI unit. - */ -#define STM32_EXTI0_HANDLER Vector58 -#define STM32_EXTI1_HANDLER Vector5C -#define STM32_EXTI2_HANDLER Vector60 -#define STM32_EXTI3_HANDLER Vector64 -#define STM32_EXTI4_HANDLER Vector68 -#define STM32_EXTI5_9_HANDLER Vector9C -#define STM32_EXTI10_15_HANDLER VectorE0 -#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1 PVM4 */ -#define STM32_EXTI18_HANDLER VectorE4 /* RTC ALARM */ -#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */ -#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */ -#define STM32_EXTI21_22_HANDLER Vector140 /* COMP1..2 */ - -#define STM32_EXTI0_NUMBER 6 -#define STM32_EXTI1_NUMBER 7 -#define STM32_EXTI2_NUMBER 8 -#define STM32_EXTI3_NUMBER 9 -#define STM32_EXTI4_NUMBER 10 -#define STM32_EXTI5_9_NUMBER 23 -#define STM32_EXTI10_15_NUMBER 40 -#define STM32_EXTI1635_38_NUMBER 1 -#define STM32_EXTI18_NUMBER 41 -#define STM32_EXTI19_NUMBER 2 -#define STM32_EXTI20_NUMBER 3 -#define STM32_EXTI21_22_NUMBER 64 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C3_EVENT_HANDLER Vector160 -#define STM32_I2C3_ERROR_HANDLER Vector164 -#define STM32_I2C4_EVENT_HANDLER Vector18C -#define STM32_I2C4_ERROR_HANDLER Vector190 - -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 -#define STM32_I2C3_EVENT_NUMBER 72 -#define STM32_I2C3_ERROR_NUMBER 73 -#define STM32_I2C4_EVENT_NUMBER 83 -#define STM32_I2C4_ERROR_NUMBER 84 - -/* - * QUADSPI unit. - */ -#define STM32_QUADSPI1_HANDLER Vector15C - -#define STM32_QUADSPI1_NUMBER 71 - -/* - * SDMMC unit. - */ -#define STM32_SDMMC1_HANDLER Vector104 - -#define STM32_SDMMC1_NUMBER 49 - -/* - * TIM units. - */ -#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0 -#define STM32_TIM1_UP_TIM16_HANDLER VectorA4 -#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_BRK_HANDLER VectorEC -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_TRGCO_HANDLER VectorF4 -#define STM32_TIM8_CC_HANDLER VectorF8 - -#define STM32_TIM1_BRK_TIM15_NUMBER 24 -#define STM32_TIM1_UP_TIM16_NUMBER 25 -#define STM32_TIM1_TRGCO_TIM17_NUMBER 26 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_BRK_NUMBER 43 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_TRGCO_NUMBER 45 -#define STM32_TIM8_CC_NUMBER 46 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_LPUART1_HANDLER Vector158 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_LPUART1_NUMBER 70 - -/* - * USB/OTG units. - */ -#define STM32_USB1_HP_HANDLER Vector14C -#define STM32_USB1_LP_HANDLER Vector14C -#define STM32_OTG1_HANDLER Vector14C - -#define STM32_USB1_HP_NUMBER 67 -#define STM32_USB1_LP_NUMBER 67 -#define STM32_OTG1_NUMBER 67 - -/* - * DMA2D unit. - */ -#define STM32_DMA2D_HANDLER Vector1A8 - -#define STM32_DMA2D_NUMBER 90 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx/stm32_isr.h + * @brief STM32L4xx ISR handler header. + * + * @addtogroup SRM32L4xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM8_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC unit. + */ +#define STM32_ADC1_HANDLER Vector88 +#define STM32_ADC2_HANDLER Vector88 +#define STM32_ADC3_HANDLER VectorFC + +#define STM32_ADC1_NUMBER 18 +#define STM32_ADC2_NUMBER 18 +#define STM32_ADC3_NUMBER 47 + +/* + * CAN unit. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 +#define STM32_CAN2_TX_HANDLER Vector198 +#define STM32_CAN2_RX0_HANDLER Vector19C +#define STM32_CAN2_RX1_HANDLER Vector1A0 +#define STM32_CAN2_SCE_HANDLER Vector1A4 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 +#define STM32_CAN2_TX_NUMBER 86 +#define STM32_CAN2_RX0_NUMBER 87 +#define STM32_CAN2_RX1_NUMBER 88 +#define STM32_CAN2_SCE_NUMBER 89 + +/* + * DMA unit. + */ +#define STM32_DMA1_CH1_HANDLER Vector6C +#define STM32_DMA1_CH2_HANDLER Vector70 +#define STM32_DMA1_CH3_HANDLER Vector74 +#define STM32_DMA1_CH4_HANDLER Vector78 +#define STM32_DMA1_CH5_HANDLER Vector7C +#define STM32_DMA1_CH6_HANDLER Vector80 +#define STM32_DMA1_CH7_HANDLER Vector84 +#define STM32_DMA2_CH1_HANDLER Vector120 +#define STM32_DMA2_CH2_HANDLER Vector124 +#define STM32_DMA2_CH3_HANDLER Vector128 +#define STM32_DMA2_CH4_HANDLER Vector12C +#define STM32_DMA2_CH5_HANDLER Vector130 +#define STM32_DMA2_CH6_HANDLER Vector150 +#define STM32_DMA2_CH7_HANDLER Vector154 + +#define STM32_DMA1_CH1_NUMBER 11 +#define STM32_DMA1_CH2_NUMBER 12 +#define STM32_DMA1_CH3_NUMBER 13 +#define STM32_DMA1_CH4_NUMBER 14 +#define STM32_DMA1_CH5_NUMBER 15 +#define STM32_DMA1_CH6_NUMBER 16 +#define STM32_DMA1_CH7_NUMBER 17 +#define STM32_DMA2_CH1_NUMBER 56 +#define STM32_DMA2_CH2_NUMBER 57 +#define STM32_DMA2_CH3_NUMBER 58 +#define STM32_DMA2_CH4_NUMBER 59 +#define STM32_DMA2_CH5_NUMBER 60 +#define STM32_DMA2_CH6_NUMBER 68 +#define STM32_DMA2_CH7_NUMBER 69 + +/* + * EXTI unit. + */ +#define STM32_EXTI0_HANDLER Vector58 +#define STM32_EXTI1_HANDLER Vector5C +#define STM32_EXTI2_HANDLER Vector60 +#define STM32_EXTI3_HANDLER Vector64 +#define STM32_EXTI4_HANDLER Vector68 +#define STM32_EXTI5_9_HANDLER Vector9C +#define STM32_EXTI10_15_HANDLER VectorE0 +#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1 PVM4 */ +#define STM32_EXTI18_HANDLER VectorE4 /* RTC ALARM */ +#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */ +#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */ +#define STM32_EXTI21_22_HANDLER Vector140 /* COMP1..2 */ + +#define STM32_EXTI0_NUMBER 6 +#define STM32_EXTI1_NUMBER 7 +#define STM32_EXTI2_NUMBER 8 +#define STM32_EXTI3_NUMBER 9 +#define STM32_EXTI4_NUMBER 10 +#define STM32_EXTI5_9_NUMBER 23 +#define STM32_EXTI10_15_NUMBER 40 +#define STM32_EXTI1635_38_NUMBER 1 +#define STM32_EXTI18_NUMBER 41 +#define STM32_EXTI19_NUMBER 2 +#define STM32_EXTI20_NUMBER 3 +#define STM32_EXTI21_22_NUMBER 64 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C3_EVENT_HANDLER Vector160 +#define STM32_I2C3_ERROR_HANDLER Vector164 +#define STM32_I2C4_EVENT_HANDLER Vector18C +#define STM32_I2C4_ERROR_HANDLER Vector190 + +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 +#define STM32_I2C3_EVENT_NUMBER 72 +#define STM32_I2C3_ERROR_NUMBER 73 +#define STM32_I2C4_EVENT_NUMBER 83 +#define STM32_I2C4_ERROR_NUMBER 84 + +/* + * QUADSPI unit. + */ +#define STM32_QUADSPI1_HANDLER Vector15C + +#define STM32_QUADSPI1_NUMBER 71 + +/* + * SDMMC unit. + */ +#define STM32_SDMMC1_HANDLER Vector104 + +#define STM32_SDMMC1_NUMBER 49 + +/* + * TIM units. + */ +#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0 +#define STM32_TIM1_UP_TIM16_HANDLER VectorA4 +#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_BRK_HANDLER VectorEC +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_TRGCO_HANDLER VectorF4 +#define STM32_TIM8_CC_HANDLER VectorF8 + +#define STM32_TIM1_BRK_TIM15_NUMBER 24 +#define STM32_TIM1_UP_TIM16_NUMBER 25 +#define STM32_TIM1_TRGCO_TIM17_NUMBER 26 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_BRK_NUMBER 43 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_TRGCO_NUMBER 45 +#define STM32_TIM8_CC_NUMBER 46 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_LPUART1_HANDLER Vector158 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_LPUART1_NUMBER 70 + +/* + * USB/OTG units. + */ +#define STM32_USB1_HP_HANDLER Vector14C +#define STM32_USB1_LP_HANDLER Vector14C +#define STM32_OTG1_HANDLER Vector14C + +#define STM32_USB1_HP_NUMBER 67 +#define STM32_USB1_LP_NUMBER 67 +#define STM32_OTG1_NUMBER 67 + +/* + * DMA2D unit. + */ +#define STM32_DMA2D_HANDLER Vector1A8 + +#define STM32_DMA2D_NUMBER 90 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h b/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h index de3acfae65..5a18b91bbe 100644 --- a/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h @@ -1,1279 +1,1279 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32l4xx.h. - * - * @addtogroup STM32L4xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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 (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R1(mask, lp) { \ - RCC->APB1ENR1 |= (mask); \ - if (lp) \ - RCC->APB1SMENR1 |= (mask); \ - else \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccDisableAPB1R1(mask) { \ - RCC->APB1ENR1 &= ~(mask); \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccResetAPB1R1(mask) { \ - RCC->APB1RSTR1 |= (mask); \ - RCC->APB1RSTR1 &= ~(mask); \ - (void)RCC->APB1RSTR1; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R2(mask, lp) { \ - RCC->APB1ENR2 |= (mask); \ - if (lp) \ - RCC->APB1SMENR2 |= (mask); \ - else \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccDisableAPB1R2(mask) { \ - RCC->APB1ENR2 &= ~(mask); \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccResetAPB1R2(mask) { \ - RCC->APB1RSTR2 |= (mask); \ - RCC->APB1RSTR2 &= ~(mask); \ - (void)RCC->APB1RSTR2; \ -} - -/** - * @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->APB2SMENR |= (mask); \ - else \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @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->AHB1SMENR |= (mask); \ - else \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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->AHB2SMENR |= (mask); \ - else \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @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->AHB3SMENR |= (mask); \ - else \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2/ADC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC123(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp) - -/** - * @brief Disables the ADC1/ADC2/ADC3 peripheral clock. - * - * @api - */ -#define rccDisableADC123() rccDisableAHB2(RCC_AHB2ENR_ADCEN) - -/** - * @brief Resets the ADC1/ADC2/ADC3 peripheral. - * - * @api - */ -#define rccResetADC123() rccResetAHB2(RCC_AHB2RSTR_ADCRST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @api - */ -#define rccDisableCAN1() rccDisableAPB1R1(RCC_APB1ENR1_CAN1EN) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1R1(RCC_APB1RSTR1_CAN1RST) - -/** - * @brief Enables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN2(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN2EN, lp) - -/** - * @brief Disables the CAN2 peripheral clock. - * - * @api - */ -#define rccDisableCAN2() rccDisableAPB1R1(RCC_APB1ENR1_CAN2EN) - -/** - * @brief Resets the CAN2 peripheral. - * - * @api - */ -#define rccResetCAN2() rccResetAPB1R1(RCC_APB1RSTR1_CAN2RST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) - -/** - * @brief Enables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) - -/** - * @brief Disables the I2C3 peripheral clock. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @api - */ -#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) - -/** - * @brief Disables the OTG_FS peripheral clock. - * - * @api - */ -#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) - -/** - * @brief Resets the OTG_FS peripheral. - * - * @api - */ -#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) -/** @} */ - -/** - * @name QUADSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the QUADSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) - -/** - * @brief Disables the QUADSPI1 peripheral clock. - * - * @api - */ -#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) - -/** - * @brief Resets the QUADSPI1 peripheral. - * - * @api - */ -#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) -/** @} */ - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) -/** @} */ - -/** - * @name SDMMC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDMMC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp) - -/** - * @brief Disables the SDMMC1 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN) - -/** - * @brief Resets the SDMMC1 peripheral. - * - * @api - */ -#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) - -/** - * @brief Resets the FSMC peripheral. - * - * @api - */ -#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32l4xx.h. + * + * @addtogroup STM32L4xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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 (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R1(mask, lp) { \ + RCC->APB1ENR1 |= (mask); \ + if (lp) \ + RCC->APB1SMENR1 |= (mask); \ + else \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccDisableAPB1R1(mask) { \ + RCC->APB1ENR1 &= ~(mask); \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccResetAPB1R1(mask) { \ + RCC->APB1RSTR1 |= (mask); \ + RCC->APB1RSTR1 &= ~(mask); \ + (void)RCC->APB1RSTR1; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R2(mask, lp) { \ + RCC->APB1ENR2 |= (mask); \ + if (lp) \ + RCC->APB1SMENR2 |= (mask); \ + else \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccDisableAPB1R2(mask) { \ + RCC->APB1ENR2 &= ~(mask); \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccResetAPB1R2(mask) { \ + RCC->APB1RSTR2 |= (mask); \ + RCC->APB1RSTR2 &= ~(mask); \ + (void)RCC->APB1RSTR2; \ +} + +/** + * @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->APB2SMENR |= (mask); \ + else \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @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->AHB1SMENR |= (mask); \ + else \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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->AHB2SMENR |= (mask); \ + else \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @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->AHB3SMENR |= (mask); \ + else \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2/ADC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC123(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp) + +/** + * @brief Disables the ADC1/ADC2/ADC3 peripheral clock. + * + * @api + */ +#define rccDisableADC123() rccDisableAHB2(RCC_AHB2ENR_ADCEN) + +/** + * @brief Resets the ADC1/ADC2/ADC3 peripheral. + * + * @api + */ +#define rccResetADC123() rccResetAHB2(RCC_AHB2RSTR_ADCRST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @api + */ +#define rccDisableCAN1() rccDisableAPB1R1(RCC_APB1ENR1_CAN1EN) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1R1(RCC_APB1RSTR1_CAN1RST) + +/** + * @brief Enables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN2(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN2EN, lp) + +/** + * @brief Disables the CAN2 peripheral clock. + * + * @api + */ +#define rccDisableCAN2() rccDisableAPB1R1(RCC_APB1ENR1_CAN2EN) + +/** + * @brief Resets the CAN2 peripheral. + * + * @api + */ +#define rccResetCAN2() rccResetAPB1R1(RCC_APB1RSTR1_CAN2RST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) + +/** + * @brief Enables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) + +/** + * @brief Disables the I2C3 peripheral clock. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @api + */ +#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) + +/** + * @brief Disables the OTG_FS peripheral clock. + * + * @api + */ +#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN) + +/** + * @brief Resets the OTG_FS peripheral. + * + * @api + */ +#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) +/** @} */ + +/** + * @name QUADSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the QUADSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp) + +/** + * @brief Disables the QUADSPI1 peripheral clock. + * + * @api + */ +#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN) + +/** + * @brief Resets the QUADSPI1 peripheral. + * + * @api + */ +#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST) +/** @} */ + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) +/** @} */ + +/** + * @name SDMMC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDMMC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp) + +/** + * @brief Disables the SDMMC1 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN) + +/** + * @brief Resets the SDMMC1 peripheral. + * + * @api + */ +#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) + +/** + * @brief Resets the FSMC peripheral. + * + * @api + */ +#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L4xx/stm32_registry.h b/os/hal/ports/STM32/STM32L4xx/stm32_registry.h index f8ba636424..083a6a9cca 100644 --- a/os/hal/ports/STM32/STM32L4xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L4xx/stm32_registry.h @@ -1,1350 +1,1350 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L4xx/stm32_registry.h - * @brief STM32L4xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32L4xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 128 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 18 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ -} while (false) - -#if defined(STM32L486xx) || defined(STM32L4A6xx) || \ - defined(__DOXYGEN__) -#define STM32_HAS_HASH1 TRUE -#define STM32_HAS_CRYP1 TRUE -#else -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE -#endif - -/*===========================================================================*/ -/* STM32L432xx. */ -/*===========================================================================*/ - -#if defined(STM32L432xx) || defined(__DOXYGEN__) - -/* Clock attributes.*/ -#define STM32_CLOCK_HAS_HSI48 TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 14 -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_DAC1_CH1_DMA_CHN 0x00003600 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_DAC1_CH2_DMA_CHN 0x00035000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 7 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 40 -#define STM32_EXTI_IMR1_MASK 0xFF820000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD FALSE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_I2C1_RX_DMA_CHN 0x03500000 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_I2C1_TX_DMA_CHN 0x05300000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_I2C2 FALSE -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_QUADSPI1_DMA_CHN 0x03050000 - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 FALSE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_RX_DMA_CHN 0x00000410 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI1_TX_DMA_CHN 0x00004100 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE -#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_SPI3_RX_DMA_CHN 0x00000003 -#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_SPI2 FALSE -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART1_RX_DMA_CHN 0x02020000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_USART1_TX_DMA_CHN 0x00202000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00200000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x02000000 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32L432xx) */ - -/*===========================================================================*/ -/* STM32L433xx, STM32L443xx. */ -/*===========================================================================*/ - -#if defined(STM32L433xx) || defined(STM32L443xx) || defined(__DOXYGEN__) - -/* Clock attributes.*/ -#define STM32_CLOCK_HAS_HSI48 TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 14 -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_DAC1_CH1_DMA_CHN 0x00003600 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_DAC1_CH2_DMA_CHN 0x00035000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 7 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 40 -#define STM32_EXTI_IMR1_MASK 0xFF820000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 1 -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_I2C1_RX_DMA_CHN 0x03500000 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_I2C1_TX_DMA_CHN 0x05300000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C2_RX_DMA_CHN 0x00030000 -#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_I2C2_TX_DMA_CHN 0x00003000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_QUADSPI1_DMA_CHN 0x03050000 - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 - -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_RX_DMA_CHN 0x00000410 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI1_TX_DMA_CHN 0x00004100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_SPI2_RX_DMA_CHN 0x00001000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_SPI2_TX_DMA_CHN 0x00010000 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE -#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_SPI3_RX_DMA_CHN 0x00000003 -#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM3 FALSE -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART1_RX_DMA_CHN 0x02020000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_USART1_TX_DMA_CHN 0x00202000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00200000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x02000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_USART3_RX_DMA_CHN 0x00000200 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_USART3_TX_DMA_CHN 0x00000020 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32L443xx) */ - -/*===========================================================================*/ -/* STM32L452xx. */ -/*===========================================================================*/ - -#if defined(STM32L452xx) || defined(__DOXYGEN__) - -/* Clock attributes.*/ -#define STM32_CLOCK_HAS_HSI48 TRUE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 14 -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_DAC1_CH1_DMA_CHN 0x00003600 - -#define STM32_HAS_DAC1_CH2 FALSE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 7 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 40 -#define STM32_EXTI_IMR1_MASK 0xFF820000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF FALSE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_I2C1_RX_DMA_CHN 0x03500000 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_I2C1_TX_DMA_CHN 0x05300000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C2_RX_DMA_CHN 0x00030000 -#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_I2C2_TX_DMA_CHN 0x00003000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_I2C4_RX_DMA_CHN 0x00000000 -#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_I2C4_TX_DMA_CHN 0x00000000 - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_QUADSPI1_DMA_CHN 0x03050000 - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 - -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_RX_DMA_CHN 0x00000410 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI1_TX_DMA_CHN 0x00004100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_SPI2_RX_DMA_CHN 0x00001000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_SPI2_TX_DMA_CHN 0x00010000 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE -#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_SPI3_RX_DMA_CHN 0x00000003 -#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART1_RX_DMA_CHN 0x02020000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_USART1_TX_DMA_CHN 0x00202000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00200000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x02000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_USART3_RX_DMA_CHN 0x00000200 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_USART3_TX_DMA_CHN 0x00000020 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_UART4_RX_DMA_CHN 0x00020000 -#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_UART4_TX_DMA_CHN 0x00000200 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR TRUE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32L452xx) */ - -/*===========================================================================*/ -/* STM32L476xx, STM32L486xx. */ -/*===========================================================================*/ - -#if defined(STM32L476xx) || defined(STM32L486xx) - -/* Clock attributes.*/ -#define STM32_CLOCK_HAS_HSI48 FALSE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_ADC3_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 14 -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_DAC1_CH1_DMA_CHN 0x00003600 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_DAC1_CH2_DMA_CHN 0x00035000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 7 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 40 -#define STM32_EXTI_IMR1_MASK 0xFF820000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOFEN | \ - RCC_AHB2ENR_GPIOGEN | \ - RCC_AHB2ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_I2C1_RX_DMA_CHN 0x03500000 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_I2C1_TX_DMA_CHN 0x05300000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C2_RX_DMA_CHN 0x00030000 -#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_I2C2_TX_DMA_CHN 0x00003000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_I2C4 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_QUADSPI1_DMA_CHN 0x03050000 - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 - -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_RX_DMA_CHN 0x00000410 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI1_TX_DMA_CHN 0x00004100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_SPI2_RX_DMA_CHN 0x00001000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_SPI2_TX_DMA_CHN 0x00010000 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE -#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_SPI3_RX_DMA_CHN 0x00000003 -#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 2 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART1_RX_DMA_CHN 0x02020000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_USART1_TX_DMA_CHN 0x00202000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00200000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x02000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_USART3_RX_DMA_CHN 0x00000200 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_USART3_TX_DMA_CHN 0x00000020 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) -#define STM32_UART4_RX_DMA_CHN 0x00020000 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 3) -#define STM32_UART4_TX_DMA_CHN 0x00000200 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 2) -#define STM32_UART5_RX_DMA_CHN 0x00000020 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 1) -#define STM32_UART5_TX_DMA_CHN 0x00000002 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_OTG_SEQUENCE_WORKAROUND -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32L476xx) */ - -/*===========================================================================*/ -/* STM32L496xx, STM32L4A6xx. */ -/*===========================================================================*/ - -#if defined(STM32L496xx) || defined(STM32L4A6xx) - -/* Clock attributes.*/ -#define STM32_CLOCK_HAS_HSI48 FALSE - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC2_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_ADC3_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_CAN_MAX_FILTERS 28 -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_DAC1_CH1_DMA_CHN 0x00003600 - -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_DAC1_CH2_DMA_CHN 0x00035000 - -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX FALSE -#define STM32_DMA_SUPPORTS_CSELR TRUE -#define STM32_DMA1_NUM_CHANNELS 7 -#define STM32_DMA2_NUM_CHANNELS 7 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 40 -#define STM32_EXTI_IMR1_MASK 0xFF820000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 -#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) -#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ -#endif - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI TRUE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOFEN | \ - RCC_AHB2ENR_GPIOGEN | \ - RCC_AHB2ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_I2C1_RX_DMA_CHN 0x03500000 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_I2C1_TX_DMA_CHN 0x05300000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C2_RX_DMA_CHN 0x00030000 -#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_I2C2_TX_DMA_CHN 0x00003000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_I2C3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_I2C4 TRUE -#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_I2C4_RX_DMA_CHN 0x00000000 -#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_I2C4_TX_DMA_CHN 0x00000000 - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 TRUE -#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_QUADSPI1_DMA_CHN 0x03050000 - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 - -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_SPI1_RX_DMA_CHN 0x00000410 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_SPI1_TX_DMA_CHN 0x00004100 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE -#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_SPI2_RX_DMA_CHN 0x00001000 -#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_SPI2_TX_DMA_CHN 0x00010000 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE -#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_SPI3_RX_DMA_CHN 0x00000003 -#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI3_TX_DMA_CHN 0x00000030 - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART1_RX_DMA_CHN 0x02020000 -#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_USART1_TX_DMA_CHN 0x00202000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_USART2_RX_DMA_CHN 0x00200000 -#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_USART2_TX_DMA_CHN 0x02000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_USART3_RX_DMA_CHN 0x00000200 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_USART3_TX_DMA_CHN 0x00000020 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) -#define STM32_UART4_RX_DMA_CHN 0x00020000 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 3) -#define STM32_UART4_TX_DMA_CHN 0x00000200 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 2) -#define STM32_UART5_RX_DMA_CHN 0x00000020 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 1) -#define STM32_UART5_TX_DMA_CHN 0x00000002 - -#define STM32_HAS_LPUART1 TRUE - -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_OTG_STEPPING 2 -#define STM32_HAS_OTG1 TRUE -#define STM32_OTG1_ENDPOINTS 5 - -#define STM32_HAS_OTG2 FALSE -#define STM32_HAS_USB FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D TRUE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -#endif /* defined(STM32L496xx) */ - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L4xx/stm32_registry.h + * @brief STM32L4xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32L4xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 18 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ +} while (false) + +#if defined(STM32L486xx) || defined(STM32L4A6xx) || \ + defined(__DOXYGEN__) +#define STM32_HAS_HASH1 TRUE +#define STM32_HAS_CRYP1 TRUE +#else +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE +#endif + +/*===========================================================================*/ +/* STM32L432xx. */ +/*===========================================================================*/ + +#if defined(STM32L432xx) || defined(__DOXYGEN__) + +/* Clock attributes.*/ +#define STM32_CLOCK_HAS_HSI48 TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 14 +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_DAC1_CH1_DMA_CHN 0x00003600 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_DAC1_CH2_DMA_CHN 0x00035000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 7 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 40 +#define STM32_EXTI_IMR1_MASK 0xFF820000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD FALSE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_I2C1_RX_DMA_CHN 0x03500000 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_I2C1_TX_DMA_CHN 0x05300000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_I2C2 FALSE +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_QUADSPI1_DMA_CHN 0x03050000 + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 FALSE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_RX_DMA_CHN 0x00000410 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI1_TX_DMA_CHN 0x00004100 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE +#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_SPI3_RX_DMA_CHN 0x00000003 +#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_SPI2 FALSE +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART1_RX_DMA_CHN 0x02020000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_USART1_TX_DMA_CHN 0x00202000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00200000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x02000000 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32L432xx) */ + +/*===========================================================================*/ +/* STM32L433xx, STM32L443xx. */ +/*===========================================================================*/ + +#if defined(STM32L433xx) || defined(STM32L443xx) || defined(__DOXYGEN__) + +/* Clock attributes.*/ +#define STM32_CLOCK_HAS_HSI48 TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 14 +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_DAC1_CH1_DMA_CHN 0x00003600 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_DAC1_CH2_DMA_CHN 0x00035000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 7 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 40 +#define STM32_EXTI_IMR1_MASK 0xFF820000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 1 +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_I2C1_RX_DMA_CHN 0x03500000 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_I2C1_TX_DMA_CHN 0x05300000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C2_RX_DMA_CHN 0x00030000 +#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_I2C2_TX_DMA_CHN 0x00003000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_QUADSPI1_DMA_CHN 0x03050000 + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 + +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_RX_DMA_CHN 0x00000410 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI1_TX_DMA_CHN 0x00004100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_SPI2_RX_DMA_CHN 0x00001000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_SPI2_TX_DMA_CHN 0x00010000 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE +#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_SPI3_RX_DMA_CHN 0x00000003 +#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM3 FALSE +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART1_RX_DMA_CHN 0x02020000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_USART1_TX_DMA_CHN 0x00202000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00200000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x02000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_USART3_RX_DMA_CHN 0x00000200 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_USART3_TX_DMA_CHN 0x00000020 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32L443xx) */ + +/*===========================================================================*/ +/* STM32L452xx. */ +/*===========================================================================*/ + +#if defined(STM32L452xx) || defined(__DOXYGEN__) + +/* Clock attributes.*/ +#define STM32_CLOCK_HAS_HSI48 TRUE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 14 +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_DAC1_CH1_DMA_CHN 0x00003600 + +#define STM32_HAS_DAC1_CH2 FALSE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 7 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 40 +#define STM32_EXTI_IMR1_MASK 0xFF820000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF FALSE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_I2C1_RX_DMA_CHN 0x03500000 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_I2C1_TX_DMA_CHN 0x05300000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C2_RX_DMA_CHN 0x00030000 +#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_I2C2_TX_DMA_CHN 0x00003000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_I2C4_RX_DMA_CHN 0x00000000 +#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_I2C4_TX_DMA_CHN 0x00000000 + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_QUADSPI1_DMA_CHN 0x03050000 + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 + +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_RX_DMA_CHN 0x00000410 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI1_TX_DMA_CHN 0x00004100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_SPI2_RX_DMA_CHN 0x00001000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_SPI2_TX_DMA_CHN 0x00010000 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE +#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_SPI3_RX_DMA_CHN 0x00000003 +#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART1_RX_DMA_CHN 0x02020000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_USART1_TX_DMA_CHN 0x00202000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00200000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x02000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_USART3_RX_DMA_CHN 0x00000200 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_USART3_TX_DMA_CHN 0x00000020 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_UART4_RX_DMA_CHN 0x00020000 +#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_UART4_TX_DMA_CHN 0x00000200 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR TRUE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32L452xx) */ + +/*===========================================================================*/ +/* STM32L476xx, STM32L486xx. */ +/*===========================================================================*/ + +#if defined(STM32L476xx) || defined(STM32L486xx) + +/* Clock attributes.*/ +#define STM32_CLOCK_HAS_HSI48 FALSE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_ADC3_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 14 +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_DAC1_CH1_DMA_CHN 0x00003600 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_DAC1_CH2_DMA_CHN 0x00035000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 7 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 40 +#define STM32_EXTI_IMR1_MASK 0xFF820000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOFEN | \ + RCC_AHB2ENR_GPIOGEN | \ + RCC_AHB2ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_I2C1_RX_DMA_CHN 0x03500000 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_I2C1_TX_DMA_CHN 0x05300000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C2_RX_DMA_CHN 0x00030000 +#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_I2C2_TX_DMA_CHN 0x00003000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_I2C4 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_QUADSPI1_DMA_CHN 0x03050000 + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 + +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_RX_DMA_CHN 0x00000410 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI1_TX_DMA_CHN 0x00004100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_SPI2_RX_DMA_CHN 0x00001000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_SPI2_TX_DMA_CHN 0x00010000 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE +#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_SPI3_RX_DMA_CHN 0x00000003 +#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 2 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART1_RX_DMA_CHN 0x02020000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_USART1_TX_DMA_CHN 0x00202000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00200000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x02000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_USART3_RX_DMA_CHN 0x00000200 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_USART3_TX_DMA_CHN 0x00000020 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) +#define STM32_UART4_RX_DMA_CHN 0x00020000 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 3) +#define STM32_UART4_TX_DMA_CHN 0x00000200 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 2) +#define STM32_UART5_RX_DMA_CHN 0x00000020 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 1) +#define STM32_UART5_TX_DMA_CHN 0x00000002 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_OTG_SEQUENCE_WORKAROUND +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32L476xx) */ + +/*===========================================================================*/ +/* STM32L496xx, STM32L4A6xx. */ +/*===========================================================================*/ + +#if defined(STM32L496xx) || defined(STM32L4A6xx) + +/* Clock attributes.*/ +#define STM32_CLOCK_HAS_HSI48 FALSE + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC2_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_ADC3_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_CAN_MAX_FILTERS 28 +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_DAC1_CH1_DMA_CHN 0x00003600 + +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_DAC1_CH2_DMA_CHN 0x00035000 + +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX FALSE +#define STM32_DMA_SUPPORTS_CSELR TRUE +#define STM32_DMA1_NUM_CHANNELS 7 +#define STM32_DMA2_NUM_CHANNELS 7 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 40 +#define STM32_EXTI_IMR1_MASK 0xFF820000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 +#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__) +#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/ +#endif + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI TRUE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOFEN | \ + RCC_AHB2ENR_GPIOGEN | \ + RCC_AHB2ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_I2C1_RX_DMA_CHN 0x03500000 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_I2C1_TX_DMA_CHN 0x05300000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C2_RX_DMA_CHN 0x00030000 +#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_I2C2_TX_DMA_CHN 0x00003000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_I2C3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_I2C4 TRUE +#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_I2C4_RX_DMA_CHN 0x00000000 +#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_I2C4_TX_DMA_CHN 0x00000000 + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 TRUE +#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_QUADSPI1_DMA_CHN 0x03050000 + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000 + +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_SPI1_RX_DMA_CHN 0x00000410 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_SPI1_TX_DMA_CHN 0x00004100 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE +#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_SPI2_RX_DMA_CHN 0x00001000 +#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_SPI2_TX_DMA_CHN 0x00010000 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE +#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_SPI3_RX_DMA_CHN 0x00000003 +#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI3_TX_DMA_CHN 0x00000030 + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART1_RX_DMA_CHN 0x02020000 +#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_USART1_TX_DMA_CHN 0x00202000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_USART2_RX_DMA_CHN 0x00200000 +#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_USART2_TX_DMA_CHN 0x02000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_USART3_RX_DMA_CHN 0x00000200 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_USART3_TX_DMA_CHN 0x00000020 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5) +#define STM32_UART4_RX_DMA_CHN 0x00020000 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 3) +#define STM32_UART4_TX_DMA_CHN 0x00000200 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 2) +#define STM32_UART5_RX_DMA_CHN 0x00000020 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 1) +#define STM32_UART5_TX_DMA_CHN 0x00000002 + +#define STM32_HAS_LPUART1 TRUE + +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_OTG_STEPPING 2 +#define STM32_HAS_OTG1 TRUE +#define STM32_OTG1_ENDPOINTS 5 + +#define STM32_HAS_OTG2 FALSE +#define STM32_HAS_USB FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D TRUE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +#endif /* defined(STM32L496xx) */ + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L5xx/hal_lld.h b/os/hal/ports/STM32/STM32L5xx/hal_lld.h index 7425e45292..9be4751032 100644 --- a/os/hal/ports/STM32/STM32L5xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32L5xx/hal_lld.h @@ -1,2699 +1,2707 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L5xx/hal_lld.h - * @brief STM32L5xx 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_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32L4R5xx, STM32L4R7xx, STM32L4R9xx. - * - STM32L4S5xx, STM32L4S7xx, STM32L4S9xx. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef HAL_LLD_H -#define HAL_LLD_H - -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || \ - defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32L4+ Ultra Low Power" - -#elif defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) -#define PLATFORM_NAME "STM32L4+ Ultra Low Power with Crypto" - -#else -#error "STM32L4+ device not specified" -#endif - -/** - * @brief Sub-family identifier. - */ -#if !defined(STM32L5XX) || defined(__DOXYGEN__) -#define STM32L5XX -#endif -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ -#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR1 register bits definitions - * @{ - */ -#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */ -#define STM32_VOS_RANGE0 (0 << 9) /**< Core voltage 1.28 Volts. */ -#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */ -#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ -/** @} */ - -/** - * @name PWR_CR2 register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ -#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CR register bits definitions - * @{ - */ -#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */ -#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */ -#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */ -#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */ -#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */ -#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */ -#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */ -#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */ -#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */ -#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */ -#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */ -#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */ -#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ -#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ -#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */ -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */ -#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */ -#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */ - -#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ -#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ -#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ -#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ - -#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ -#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ -#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ -#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ -#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ -#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */ -#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ - -/** - * @name RCC_PLLSAI1CFGR register bits definitions - * @{ - */ -#define STM32_PLLSAI1SRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSAI1SRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSAI1SRC_MSI (1 << 0) /**< PLL clock source is MSI. */ -#define STM32_PLLSAI1SRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSAI1SRC_HSE (3 << 0) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_PLLSAI2CFGR register bits definitions - * @{ - */ -#define STM32_PLLSAI2SRC_MASK (3 << 0) /**< PLL clock source mask. */ -#define STM32_PLLSAI2SRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ -#define STM32_PLLSAI2SRC_MSI (1 << 0) /**< PLL clock source is MSI. */ -#define STM32_PLLSAI2SRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ -#define STM32_PLLSAI2SRC_HSE (3 << 0) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CCIPR register bits definitions - * @{ - */ -#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ -#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ -#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ -#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */ -#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ - -#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ -#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ -#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ -#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */ -#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ - -#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ -#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ -#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ -#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */ -#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ - -#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ -#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ -#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ -#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */ -#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ - -#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ -#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ -#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ -#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */ -#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ - -#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */ -#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */ -#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */ -#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */ -#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */ - -#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */ -#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */ -#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */ - -#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */ -#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */ -#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */ -#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */ - -#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */ -#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */ -#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */ -#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */ - -#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */ -#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */ -#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */ -#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */ -#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */ - -#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */ -#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */ -#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */ -#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */ -#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */ - -#define STM32_LPTIM3SEL_MASK (3 << 22) /**< LPTIM3SEL mask. */ -#define STM32_LPTIM3SEL_PCLK1 (0 << 22) /**< LPTIM3 source is PCLK1. */ -#define STM32_LPTIM3SEL_LSI (1 << 22) /**< LPTIM3 source is LSI. */ -#define STM32_LPTIM3SEL_HSI16 (2 << 22) /**< LPTIM3 source is HSI16. */ -#define STM32_LPTIM3SEL_LSE (3 << 22) /**< LPTIM3 source is LSE. */ - -#define STM32_FDCANSEL_MASK (3 << 24) /**< FDCANSEL mask. */ -#define STM32_FDCANSEL_HSE (0 << 24) /**< FDCAN source is HSE. */ -#define STM32_FDCANSEL_PLL (1 << 24) /**< FDCAN source is PLL-Q. */ -#define STM32_FDCANSEL_PLLSAI1 (2 << 24) /**< FDCAN source is PLLSAI1-P. */ - -#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */ -#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */ -#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */ -#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */ -#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */ - -#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */ -#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */ -#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */ -#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */ -/** @} */ - -/** - * @name RCC_CCIPR2 register bits definitions - * @{ - */ -#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */ -#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */ -#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */ -#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */ - -#define STM32_DFSDMSEL_MASK (1 << 2) /**< DFSDMSEL mask. */ -#define STM32_DFSDMSEL_PCLK2 (0 << 2) /**< DFSDMSEL source is PCLK2. */ -#define STM32_DFSDMSEL_SYSCLK (1 << 2) /**< DFSDMSEL source is SYSCLK. */ - -#define STM32_ADFSDMSEL_MASK (3 << 3) /**< ADFSDMSEL mask. */ -#define STM32_ADFSDMSEL_SAI1CLK (0 << 3) /**< ADFSDMSEL source is - SAI1CLK. */ -#define STM32_ADFSDMSEL_HSI16 (1 << 3) /**< ADFSDMSEL source is HSI16. */ -#define STM32_ADFSDMSEL_MSI (2 << 3) /**< ADFSDMSEL source is MSI. */ - -#define STM32_SAI1SEL_MASK (7 << 5) /**< SAI1SEL mask. */ -#define STM32_SAI1SEL_PLLSAI1 (0 << 5) /**< SAI1 source is PLLSAI1CLK. */ -#define STM32_SAI1SEL_PLLSAI2 (1 << 5) /**< SAI1 source is PLLSAI2CLK. */ -#define STM32_SAI1SEL_PLL (2 << 5) /**< SAI1 source is PLLSAI3CLK */ -#define STM32_SAI1SEL_EXTCLK (3 << 5) /**< SAI1 source is external. */ -#define STM32_SAI1SEL_HSI16 (4 << 5) /**< SAI1 source is HSI16. */ -#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ - -#define STM32_SAI2SEL_MASK (7 << 8) /**< SAI2SEL mask. */ -#define STM32_SAI2SEL_PLLSAI1 (0 << 8) /**< SAI2 source is PLLSAI1CLK. */ -#define STM32_SAI2SEL_PLLSAI2 (1 << 8) /**< SAI2 source is PLLSAI2CLK. */ -#define STM32_SAI2SEL_PLL (2 << 8) /**< SAI2 source is PLLSAI3CLK */ -#define STM32_SAI2SEL_EXTCLK (3 << 8) /**< SAI2 source is external. */ -#define STM32_SAI2SEL_HSI16 (4 << 8) /**< SAI2 source is HSI16. */ -#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ - -#define STM32_SDMMCSEL_MASK (1 << 14) /**< SDMMCSEL mask. */ -#define STM32_SDMMCSEL_48CLK (0 << 14) /**< SDMMCSEL source is 48CLK. */ -#define STM32_SDMMCSEL_PLL (1 << 14) /**< SDMMCSEL source is - PLLSAI3CLK. */ - -#define STM32_OSPISEL_MASK (3 << 20) /**< OSPISEL mask. */ -#define STM32_OSPISEL_SYSCLK (0 << 20) /**< OSPI source is SYSCLK. */ -#define STM32_OSPISEL_MSI (1 << 20) /**< OSPI source is MSI. */ -#define STM32_OSPISEL_48CLK (2 << 20) /**< OSPI source is 48CLK. */ -/** @} */ - -/** - * @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. */ - -#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */ -#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */ -#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */ -#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */ -/** @} */ - -/** - * @name RCC_CSR register bits definitions - * @{ - */ -#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */ -#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */ -#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */ -#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */ -#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_RANGE1 -#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 HSI16 clock source. - */ -#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI16_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSI48 clock source. - */ -#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI48_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Number of times to busy-loop waiting for LSE clock source. - * @note The default value of 0 disables this behavior. - * @note See also RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX 0 -#endif - -/** - * @brief Fallback RTC clock source if stopped waiting for LSE clock source. - * @note If waiting for the LSE clock source times out due to - * RUSEFI_STM32_LSE_WAIT_MAX, this allows the RTC clock source to - * fallback to another. - */ -#if !defined(RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) -#define RUSEFI_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief Enables or disables the MSI PLL on LSE clock source. - */ -#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__) -#define STM32_MSIPLL_ENABLED FALSE -#endif - -/** - * @brief MSI frequency setting. - */ -#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) -#define STM32_MSIRANGE STM32_MSIRANGE_4M -#endif - -/** - * @brief MSI frequency setting after standby. - */ -#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__) -#define STM32_MSISRANGE STM32_MSISRANGE_4M -#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 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @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 internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_MSI -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 1 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 8..127. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 60 -#endif - -/** - * @brief PLLPDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLPDIV_VALUE 0 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 7 -#endif - -/** - * @brief PLLQ divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 4 -#endif - -/** - * @brief PLLR divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLR_VALUE 2 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#endif - -/** - * @brief STOPWUCK clock setting. - */ -#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) -#define STM32_STOPWUCK STM32_STOPWUCK_MSI -#endif - -/** - * @brief MCO clock source. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief MCO divider setting. - */ -#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#endif - -/** - * @brief LSCO clock source. - */ -#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#endif - -/** - * @brief Clock source for the PLLSAL1. - */ -#if !defined(STM32_PLLSAI1SRC) || defined(__DOXYGEN__) -#define STM32_PLLSAI1SRC STM32_PLLSAI1SRC_MSI -#endif - -/** - * @brief PLLSAI1M divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSAI1M_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1M_VALUE 1 -#endif - -/** - * @brief PLLSAI1N multiplier value. - * @note The allowed values are 8..127. - */ -#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1N_VALUE 72 -#endif - -/** - * @brief PLLSAI1PDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1PDIV_VALUE 6 -#endif - -/** - * @brief PLLSAI1P divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1P_VALUE 7 -#endif - -/** - * @brief PLLSAI1Q divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1Q_VALUE 6 -#endif - -/** - * @brief PLLSAI1R divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1R_VALUE 6 -#endif - -/** - * @brief Clock source for the PLLSAL2. - */ -#if !defined(STM32_PLLSAI2SRC) || defined(__DOXYGEN__) -#define STM32_PLLSAI2SRC STM32_PLLSAI2SRC_MSI -#endif - -/** - * @brief PLLSAI2M divider value. - * @note The allowed values are 1..16. - * @note The default value is calculated for a 120MHz system clock from - * the internal 4MHz MSI clock. - */ -#if !defined(STM32_PLLSAI2M_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2M_VALUE 1 -#endif - -/** - * @brief PLLSAI2N multiplier value. - * @note The allowed values are 8..127. - */ -#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2N_VALUE 72 -#endif - -/** - * @brief PLLSAI2PDIV divider value or zero if disabled. - * @note The allowed values are 0, 2..31. - */ -#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2PDIV_VALUE 6 -#endif - -/** - * @brief PLLSAI2P divider value. - * @note The allowed values are 7, 17. - */ -#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2P_VALUE 7 -#endif - -/** - * @brief PLLSAI2Q divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI2Q_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2Q_VALUE 6 -#endif - -/** - * @brief PLLSAI2R divider value. - * @note The allowed values are 2, 4, 6, 8. - */ -#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2R_VALUE 6 -#endif - -/** - * @brief PLLSAI2DIVR value. - */ -#if !defined(STM32_PLLSAI2DIVR) || defined(__DOXYGEN__) -#define STM32_PLLSAI2DIVR STM32_PLLSAI2DIVR_DIV16 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) -#define STM32_UART5SEL STM32_UART5SEL_SYSCLK -#endif - -/** - * @brief LPUART1 clock source. - */ -#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) -#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) -#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK -#endif - -/** - * @brief I2C3 clock source. - */ -#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) -#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK -#endif - -/** - * @brief I2C4 clock source. - */ -#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) -#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK -#endif - -/** - * @brief LPTIM1 clock source. - */ -#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#endif - -/** - * @brief LPTIM2 clock source. - */ -#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 -#endif - -/** - * @brief LPTIM3 clock source. - */ -#if !defined(STM32_LPTIM3SEL) || defined(__DOXYGEN__) -#define STM32_LPTIM3SEL STM32_LPTIM3SEL_PCLK1 -#endif - -/** - * @brief FDCAN value (48MHz clock source). - */ -#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__) -#define STM32_FDCANSEL STM32_FDCANSEL_PLL -#endif - -/** - * @brief CLK48SEL value (48MHz clock source). - */ -#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) -#define STM32_CLK48SEL STM32_CLK48SEL_PLL -#endif - -/** - * @brief ADCSEL value (ADCs clock source). - */ -#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) -#define STM32_ADCSEL STM32_ADCSEL_SYSCLK -#endif - -/** - * @brief DFSDMSEL value (DFSDM clock source). - */ -#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__) -#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 -#endif - -/** - * @brief ADFSDMSEL value (DFSDM clock source). - */ -#if !defined(STM32_ADFSDMSEL) || defined(__DOXYGEN__) -#define STM32_ADFSDMSEL STM32_ADFSDMSEL_SAI1CLK -#endif - -/** - * @brief SAI1SEL value (SAI1 clock source). - */ -#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#endif - -/** - * @brief SAI2SEL value (SAI2 clock source). - */ -#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#endif - -/** - * @brief SDMMC value (SDMMC clock source). - */ -#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__) -#define STM32_SDMMCSEL STM32_SDMMCSEL_48CLK -#endif - -/** - * @brief OSPISEL value (OSPISEL clock source). - */ -#if !defined(STM32_OSPISEL) || defined(__DOXYGEN__) -#define STM32_OSPISEL STM32_OSPISEL_SYSCLK -#endif - -/** - * @brief RTC/LCD clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32L5xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L5xx_MCUCONF not defined" -#endif - -#if defined(STM32L5YYxx) && !defined(STM32L5YY_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32L5YY_MCUCONF not defined" - -#endif - -/* - * Board files sanity checks. - */ -#if !defined(STM32_LSECLK) -#error "STM32_LSECLK not defined in board.h" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined in board.h" -#endif - -#if !defined(STM32_HSECLK) -#error "STM32_HSECLK not defined in board.h" -#endif - -/* Voltage related limits.*/ -#if (STM32_VOS == STM32_VOS_RANGE0) || defined(__DOXYGEN__) -/** - * @name System Limits - * @{ - */ -/** - * @brief Maximum SYSCLK clock frequency. - */ -#define STM32_SYSCLK_MAX 110000000 - -/** - * @brief Maximum HSE clock frequency at current voltage setting. - */ -#define STM32_HSECLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MAX 48000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 4000000 - -/** - * @brief Minimum HSE clock frequency using an external source. - */ -#define STM32_HSECLK_BYP_MIN 8000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 32768 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_BYP_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 16000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 2660000 - -/** - * @brief Maximum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MAX 344000000 - -/** - * @brief Minimum VCO clock frequency at current voltage setting. - */ -#define STM32_PLLVCO_MIN 64000000 - -/** - * @brief Maximum PLL-P output clock frequency. - */ -#define STM32_PLLP_MAX 110000000 - -/** - * @brief Minimum PLL-P output clock frequency. - */ -#define STM32_PLLP_MIN 2064500 - -/** - * @brief Maximum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MAX 110000000 - -/** - * @brief Minimum PLL-Q output clock frequency. - */ -#define STM32_PLLQ_MIN 8000000 - -/** - * @brief Maximum PLL-R output clock frequency. - */ -#define STM32_PLLR_MAX 110000000 - -/** - * @brief Minimum PLL-R output clock frequency. - */ -#define STM32_PLLR_MIN 8000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 110000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 110000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 80000000 -/** @} */ - -/** - * @name Flash Wait states - * @{ - */ -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 100000000 -#define STM32_5WS_THRESHOLD 110000000 -/** @} */ - -#elif STM32_VOS == STM32_VOS_RANGE1 -#define STM32_SYSCLK_MAX 80000000 -#define STM32_HSECLK_MAX 48000000 -#define STM32_HSECLK_BYP_MAX 48000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2660000 -#define STM32_PLLVCO_MAX 344000000 -#define STM32_PLLVCO_MIN 64000000 -#define STM32_PLLP_MAX 110000000 -#define STM32_PLLP_MIN 2064500 -#define STM32_PLLQ_MAX 110000000 -#define STM32_PLLQ_MIN 8000000 -#define STM32_PLLR_MAX 110000000 -#define STM32_PLLR_MIN 8000000 -#define STM32_PCLK1_MAX 80000000 -#define STM32_PCLK2_MAX 80000000 -#define STM32_ADCCLK_MAX 80000000 - -#define STM32_0WS_THRESHOLD 20000000 -#define STM32_1WS_THRESHOLD 40000000 -#define STM32_2WS_THRESHOLD 60000000 -#define STM32_3WS_THRESHOLD 80000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 - -#elif STM32_VOS == STM32_VOS_RANGE2 -#define STM32_SYSCLK_MAX 26000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_BYP_MAX 26000000 -#define STM32_HSECLK_MIN 4000000 -#define STM32_HSECLK_BYP_MIN 8000000 -#define STM32_LSECLK_MAX 32768 -#define STM32_LSECLK_BYP_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_LSECLK_BYP_MIN 32768 -#define STM32_PLLIN_MAX 16000000 -#define STM32_PLLIN_MIN 2660000 -#define STM32_PLLVCO_MAX 128000000 -#define STM32_PLLVCO_MIN 64000000 -#define STM32_PLLP_MAX 26000000 -#define STM32_PLLP_MIN 2064500 -#define STM32_PLLQ_MAX 26000000 -#define STM32_PLLQ_MIN 8000000 -#define STM32_PLLR_MAX 26000000 -#define STM32_PLLR_MIN 8000000 -#define STM32_PCLK1_MAX 26000000 -#define STM32_PCLK2_MAX 26000000 -#define STM32_ADCCLK_MAX 26000000 - -#define STM32_0WS_THRESHOLD 8000000 -#define STM32_1WS_THRESHOLD 16000000 -#define STM32_2WS_THRESHOLD 26000000 -#define STM32_3WS_THRESHOLD 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 - -#else - #error "invalid STM32_VOS value specified" -#endif - -/** - * @brief MSI frequency. - */ -#if STM32_MSIRANGE == STM32_MSIRANGE_100K - #define STM32_MSICLK 100000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_200K - #define STM32_MSICLK 200000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_400K - #define STM32_MSICLK 400000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_800K - #define STM32_MSICLK 800000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_1M - #define STM32_MSICLK 1000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_2M - #define STM32_MSICLK 2000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_4M - #define STM32_MSICLK 4000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_8M - #define STM32_MSICLK 8000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_16M - #define STM32_MSICLK 16000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_24M - #define STM32_MSICLK 24000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_32M - #define STM32_MSICLK 32000000 -#elif STM32_MSIRANGE == STM32_MSIRANGE_48M - #define STM32_MSICLK 48000000 -#else - #error "invalid STM32_MSIRANGE value specified" -#endif - -/** - * @brief MSIS frequency. - */ -#if STM32_MSISRANGE == STM32_MSISRANGE_1M - #define STM32_MSISCLK 1000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_2M - #define STM32_MSISCLK 2000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_4M - #define STM32_MSISCLK 4000000 -#elif STM32_MSISRANGE == STM32_MSISRANGE_8M - #define STM32_MSISCLK 8000000 -#else - #error "invalid STM32_MSISRANGE value specified" -#endif - -/* - * HSI16 related checks. - */ -#if STM32_HSI16_ENABLED -#else /* !STM32_HSI16_ENABLED */ - - #if STM32_SW == STM32_SW_HSI16 - #error "HSI16 not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) - #error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - /* MCO-related checks.*/ - #if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16)) - #error "HSI16 not enabled, required by STM32_MCOSEL" - #endif - - /* SAI1-related checks.*/ - #if STM32_SAI1SEL == STM32_SAI1SEL_HSI16 - #error "HSI16 not enabled, required by STM32_SAI1SEL" - #endif - - #if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16) - #error "HSI16 not enabled, required by STM32_SAI1SEL" - #endif - - #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) && \ - (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSI16) - #error "HSI16 not enabled, required by STM32_PLLSAI1SRC" - #endif - - #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) && \ - (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSI16) - #error "HSI16 not enabled, required by STM32_PLLSAI2SRC" - #endif - - /* SAI2-related checks.*/ - #if STM32_SAI2SEL == STM32_SAI12SEL_HSI16 - #error "HSI16 not enabled, required by STM32_SAI2SEL" - #endif - - #if (STM32_SAI2SEL == STM32_SAI2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI16) - #error "HSI16 not enabled, required by STM32_SAI2SEL" - #endif - - #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) && \ - (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSI16) - #error "HSI16 not enabled, required by STM32_PLLSAI1SRC" - #endif - - #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) && \ - (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSI16) - #error "HSI16 not enabled, required by STM32_PLLSAI2SRC" - #endif - - /* USART/UART-related checks.*/ - #if (STM32_USART1SEL == STM32_USART1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_USART1SEL" - #endif - #if (STM32_USART2SEL == STM32_USART2SEL_HSI16) - #error "HSI16 not enabled, required by STM32_USART2SEL" - #endif - #if (STM32_USART3SEL == STM32_USART3SEL_HSI16) - #error "HSI16 not enabled, required by STM32_USART3SEL" - #endif - #if (STM32_UART4SEL == STM32_UART4SEL_HSI16) - #error "HSI16 not enabled, required by STM32_UART4SEL" - #endif - #if (STM32_UART5SEL == STM32_UART5SEL_HSI16) - #error "HSI16 not enabled, required by STM32_UART5SEL" - #endif - #if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) - #error "HSI16 not enabled, required by STM32_LPUART1SEL" - #endif - - /* I2C-related checks.*/ - #if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) - #error "HSI16 not enabled, required by I2C1SEL" - #endif - #if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) - #error "HSI16 not enabled, required by I2C2SEL" - #endif - #if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) - #error "HSI16 not enabled, required by I2C3SEL" - #endif - #if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) - #error "HSI16 not enabled, required by I2C4SEL" - #endif - - /* LPTIM-related checks.*/ - #if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) - #error "HSI16 not enabled, required by LPTIM1SEL" - #endif - #if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) - #error "HSI16 not enabled, required by LPTIM2SEL" - #endif - - #if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16) - #error "HSI16 not enabled, required by STM32_STOPWUCK" - #endif - -#endif /* !STM32_HSI16_ENABLED */ - -#if STM32_HSI48_ENABLED -#else /* !STM32_HSI48_ENABLED */ - - #if STM32_MCOSEL == STM32_MCOSEL_HSI48 - #error "HSI48 not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 - #error "HSI48 not enabled, required by STM32_CLK48SEL" - #endif - -#endif /* !STM32_HSI48_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - - #if STM32_HSECLK == 0 - #error "HSE frequency not defined" - #else /* STM32_HSECLK != 0 */ - #if defined(STM32_HSE_BYPASS) - #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" - #endif - #else /* !defined(STM32_HSE_BYPASS) */ - #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) - #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" - #endif - #endif /* !defined(STM32_HSE_BYPASS) */ - #endif /* STM32_HSECLK != 0 */ - -#else /* !STM32_HSE_ENABLED */ - - #if STM32_SW == STM32_SW_HSE - #error "HSE not enabled, required by STM32_SW" - #endif - - #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" - #endif - - /* MCO-related checks.*/ - #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) - #error "HSE not enabled, required by STM32_MCOSEL" - #endif - - /* SAI1-related checks.*/ - #if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SAI1SEL" - #endif - - #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) && \ - (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSE) - #error "HSE not enabled, required by STM32_PLLSAI1SRC" - #endif - - #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) && \ - (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSE) - #error "HSE not enabled, required by STM32_PLLSAI2SRC" - #endif - - /* SAI2-related checks.*/ - #if (STM32_SAI2SEL == STM32_SAI2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) - #error "HSE not enabled, required by STM32_SAI2SEL" - #endif - - #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) && \ - (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSE) - #error "HSE not enabled, required by STM32_PLLSAI1SRC" - #endif - - #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) && \ - (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSE) - #error "HSE not enabled, required by STM32_PLLSAI2SRC" - #endif - - /* RTC-related checks.*/ - #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV - #error "HSE not enabled, required by STM32_RTCSEL" - #endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - - #if STM32_RTCSEL == STM32_RTCSEL_LSI - #error "LSI not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSI - #error "LSI not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSI - #error "LSI not enabled, required by STM32_LSCOSEL" - #endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - - #if (STM32_LSECLK == 0) - #error "LSE frequency not defined" - #endif - - #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) - #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" - #endif - -#else /* !STM32_LSE_ENABLED */ - - #if STM32_RTCSEL == STM32_RTCSEL_LSE - #error "LSE not enabled, required by STM32_RTCSEL" - #endif - - #if STM32_MCOSEL == STM32_MCOSEL_LSE - #error "LSE not enabled, required by STM32_MCOSEL" - #endif - - #if STM32_LSCOSEL == STM32_LSCOSEL_LSE - #error "LSE not enabled, required by STM32_LSCOSEL" - #endif - - #if STM32_MSIPLL_ENABLED == TRUE - #error "LSE not enabled, required by STM32_MSIPLL_ENABLED" - #endif - -#endif /* !STM32_LSE_ENABLED */ - -/* - * MSI related checks. - */ -#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED - #warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED" -#endif - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \ - defined(__DOXYGEN__) - #define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) -#else - #error "invalid STM32_PLLM_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) - #define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_MSI - #define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 - #define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) - -#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK - #define STM32_PLLCLKIN 0 - -#else - #error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLL input frequency range check. - */ -#if (STM32_PLLCLKIN != 0) && \ - ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) - #error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ - defined(__DOXYGEN__) - - #if STM32_PLLCLKIN == 0 - #error "PLL activation required but no PLL clock selected" - #endif - -/** - * @brief PLL activation flag. - */ - #define STM32_ACTIVATE_PLL TRUE -#else - #define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 8) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLP (0 << 17) - -#elif STM32_PLLP_VALUE == 17 -#define STM32_PLLP (1 << 17) - -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLQ (0 << 21) - -#elif STM32_PLLQ_VALUE == 4 -#define STM32_PLLQ (1 << 21) - -#elif STM32_PLLQ_VALUE == 6 -#define STM32_PLLQ (2 << 21) - -#elif STM32_PLLQ_VALUE == 8 -#define STM32_PLLQ (3 << 21) - -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief STM32_PLLR field. - */ -#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLR (0 << 25) - -#elif STM32_PLLR_VALUE == 4 -#define STM32_PLLR (1 << 25) - -#elif STM32_PLLR_VALUE == 6 -#define STM32_PLLR (2 << 25) - -#elif STM32_PLLR_VALUE == 8 -#define STM32_PLLR (3 << 25) - -#else -#error "invalid STM32_PLLR_VALUE value specified" -#endif - -/** - * @brief STM32_PLLPDIV field. - */ -#if (STM32_PLLPDIV_VALUE == 0) || \ - ((STM32_PLLPDIV_VALUE != 1) && (STM32_PLLPDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) -#else -#error "invalid STM32_PLLPDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLPEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ - defined(__DOXYGEN__) -#define STM32_PLLPEN (1 << 16) -#else -#define STM32_PLLPEN (0 << 16) -#endif - -/** - * @brief STM32_PLLQEN field. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__) -#define STM32_PLLQEN (1 << 20) -#else -#define STM32_PLLQEN (0 << 20) -#endif - -/** - * @brief STM32_PLLREN field. - */ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ - defined(__DOXYGEN__) -#define STM32_PLLREN (1 << 24) -#else -#define STM32_PLLREN (0 << 24) -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL P output clock frequency. - */ -#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) -#else -#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) -#endif - -/** - * @brief PLL Q output clock frequency. - */ -#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) - -/** - * @brief PLL R output clock frequency. - */ -#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) - -/* - * PLL-P output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLL-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLL-R output frequency range check. - */ -#if STM32_ACTIVATE_PLL && \ - ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_MSICLK - -#elif (STM32_SW == STM32_SW_MSI) -#define STM32_SYSCLK STM32_MSICLK - -#elif (STM32_SW == STM32_SW_HSI16) -#define STM32_SYSCLK STM32_HSI16CLK - -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK - -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLL_R_CLKOUT - -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) - -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) - -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) - -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) - -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) - -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) - -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) - -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) - -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) - -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) - -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) - -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) - -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief STM32_PLLSAI1M field. - */ -#if ((STM32_PLLSAI1M_VALUE >= 1) && (STM32_PLLSAI1M_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1M ((STM32_PLLSAI1M_VALUE - 1) << 4) -#else -#error "invalid STM32_PLLSAI1M_VALUE value specified" -#endif - -/** - * @brief PLLSAI1 input clock frequency. - */ -#if (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSAI1CLKIN (STM32_HSECLK / STM32_PLLSAI1M_VALUE) - -#elif STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_MSI -#define STM32_PLLSAI1CLKIN (STM32_MSICLK / STM32_PLLSAI1M_VALUE) - -#elif STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSI16 -#define STM32_PLLSAI1CLKIN (STM32_HSI16CLK / STM32_PLLSAI1M_VALUE) - -#elif STM32_PLLSSAI1RC == STM32_PLLSAI1SRC_NOCLOCK -#define STM32_PLLSAI1CLKIN 0 - -#else -#error "invalid STM32_PLLSAI1SRC value specified" -#endif - -/* - * PLLSAI1 input frequency range check. - */ -#if (STM32_PLLSAI1CLKIN != 0) && \ - ((STM32_PLLSAI1CLKIN < STM32_PLLIN_MIN) || \ - (STM32_PLLSAI1CLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLSAI1CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLLSAI1 enable check. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \ - (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ - defined(__DOXYGEN__) - -#if STM32_PLLSAI1CLKIN == 0 -#error "PLLSAI1 activation required but no PLL clock selected" -#endif - -/** - * @brief PLLSAI1 activation flag. - */ -#define STM32_ACTIVATE_PLLSAI1 TRUE -#else -#define STM32_ACTIVATE_PLLSAI1 FALSE -#endif - -/** - * @brief STM32_PLLSAI1N field. - */ -#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 127)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8) -#else -#error "invalid STM32_PLLSAI1N_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1P field. - */ -#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLSAI1P (0 << 17) - -#elif STM32_PLLSAI1P_VALUE == 17 -#define STM32_PLLSAI1P (1 << 17) - -#else -#error "invalid STM32_PLLSAI1P_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1Q field. - */ -#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI1Q (0 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 4 -#define STM32_PLLSAI1Q (1 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 6 -#define STM32_PLLSAI1Q (2 << 21) - -#elif STM32_PLLSAI1Q_VALUE == 8 -#define STM32_PLLSAI1Q (3 << 21) - -#else -#error "invalid STM32_PLLSAI1Q_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1R field. - */ -#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI1R (0 << 25) - -#elif STM32_PLLSAI1R_VALUE == 4 -#define STM32_PLLSAI1R (1 << 25) - -#elif STM32_PLLSAI1R_VALUE == 6 -#define STM32_PLLSAI1R (2 << 25) - -#elif STM32_PLLSAI1R_VALUE == 8 -#define STM32_PLLSAI1R (3 << 25) - -#else -#error "invalid STM32_PLLSAI1R_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1PDIV field. - */ -#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27) -#else -#error "invalid STM32_PLLSAI1PDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI1PEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI1PEN (1 << 16) -#else -#define STM32_PLLSAI1PEN (0 << 16) -#endif - -/** - * @brief STM32_PLLSAI1QEN field. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_PLLSAI1QEN (1 << 20) -#else -#define STM32_PLLSAI1QEN (0 << 20) -#endif - -/** - * @brief STM32_PLLSAI1REN field. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_PLLSAI1REN (1 << 24) -#else -#define STM32_PLLSAI1REN (0 << 24) -#endif - -/** - * @brief PLLSAI1 VCO frequency. - */ -#define STM32_PLLSAI1VCO (STM32_PLLSAI1CLKIN * STM32_PLLSAI1N_VALUE) - -/* - * PLLSAI1 VCO frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI1-P output clock frequency. - */ -#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE) -#else -#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE) -#endif - -/** - * @brief PLLSAI1-Q output clock frequency. - */ -#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) - -/** - * @brief PLLSAI1-R output clock frequency. - */ -#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE) - -/* - * PLLSAI1-P output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLLSAI1-Q output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX)) -#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" -#endif - -/* - * PLLSAI1-R output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI1 && \ - ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief STM32_PLLSAI2M field. - */ -#if ((STM32_PLLSAI2M_VALUE >= 1) && (STM32_PLLSAI2M_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2M ((STM32_PLLSAI2M_VALUE - 1) << 4) -#else -#error "invalid STM32_PLLSAI2M_VALUE value specified" -#endif - -/** - * @brief PLLSAI2 input clock frequency. - */ -#if (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLSAI2CLKIN (STM32_HSECLK / STM32_PLLSAI2M_VALUE) - -#elif STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_MSI -#define STM32_PLLSAI2CLKIN (STM32_MSICLK / STM32_PLLSAI2M_VALUE) - -#elif STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSI16 -#define STM32_PLLSAI2CLKIN (STM32_HSI16CLK / STM32_PLLSAI2M_VALUE) - -#elif STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_NOCLOCK -#define STM32_PLLSAI2CLKIN 0 - -#else -#error "invalid STM32_PLLSAI2SRC value specified" -#endif - -/* - * PLLSAI2 input frequency range check. - */ -#if (STM32_PLLSAI2CLKIN != 0) && \ - ((STM32_PLLSAI2CLKIN < STM32_PLLIN_MIN) || \ - (STM32_PLLSAI2CLKIN > STM32_PLLIN_MAX)) -#error "STM32_PLLSAI2CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLLSAI2 enable check. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ - (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ - defined(__DOXYGEN__) - -#if STM32_PLLSAI2CLKIN == 0 -#error "PLLSAI2 activation required but no PLL clock selected" -#endif - -/** - * @brief PLLSAI2 activation flag. - */ -#define STM32_ACTIVATE_PLLSAI2 TRUE -#else -#define STM32_ACTIVATE_PLLSAI2 FALSE -#endif - -/** - * @brief STM32_PLLSAI2N field. - */ -#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 127)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8) -#else -#error "invalid STM32_PLLSAI2N_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2P field. - */ -#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__) -#define STM32_PLLSAI2P (0 << 17) - -#elif STM32_PLLSAI2P_VALUE == 17 -#define STM32_PLLSAI2P (1 << 17) - -#else -#error "invalid STM32_PLLSAI2P_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2R field. - */ -#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLSAI2R (0 << 25) - -#elif STM32_PLLSAI2R_VALUE == 4 -#define STM32_PLLSAI2R (1 << 25) - -#elif STM32_PLLSAI2R_VALUE == 6 -#define STM32_PLLSAI2R (2 << 25) - -#elif STM32_PLLSAI2R_VALUE == 8 -#define STM32_PLLSAI2R (3 << 25) - -#else -#error "invalid STM32_PLLSAI2R_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2PDIV field. - */ -#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27) -#else -#error "invalid STM32_PLLSAI2PDIV_VALUE value specified" -#endif - -/** - * @brief STM32_PLLSAI2PEN field. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ - (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ - defined(__DOXYGEN__) -#define STM32_PLLSAI2PEN (1 << 16) -#else -#define STM32_PLLSAI2PEN (0 << 16) -#endif - -/** - * @brief STM32_PLLSAI2REN field. - * @note Always enabled. - * @note It should depend on some condition. - */ -#define STM32_PLLSAI2REN (1 << 24) - -/** - * @brief PLLSAI2 VCO frequency. - */ -#define STM32_PLLSAI2VCO (STM32_PLLSAI2CLKIN * STM32_PLLSAI2N_VALUE) - -/* - * PLLSAI2 VCO frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX)) -#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLSAI2-P output clock frequency. - */ -#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__) -#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE) -#else -#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE) -#endif - -/** - * @brief PLLSAI2-R output clock frequency. - */ -#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE) - -/* - * PLLSAI2-P output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX)) -#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" -#endif - -/* - * PLLSAI2-R output frequency range check. - */ -#if STM32_ACTIVATE_PLLSAI2 && \ - ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX)) -#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" -#endif - -/** - * @brief MCO divider clock frequency. - */ -#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_MCODIVCLK 0 - -#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK -#define STM32_MCODIVCLK STM32_SYSCLK - -#elif STM32_MCOSEL == STM32_MCOSEL_MSI -#define STM32_MCODIVCLK STM32_MSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 -#define STM32_MCODIVCLK STM32_HSI16CLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSE -#define STM32_MCODIVCLK STM32_HSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_PLL -#define STM32_MCODIVCLK STM32_PLL_P_CLKOUT - -#elif STM32_MCOSEL == STM32_MCOSEL_LSI -#define STM32_MCODIVCLK STM32_LSICLK - -#elif STM32_MCOSEL == STM32_MCOSEL_LSE -#define STM32_MCODIVCLK STM32_LSECLK - -#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 -#define STM32_MCODIVCLK STM32_HSI48CLK - -#else -#error "invalid STM32_MCOSEL value specified" -#endif - -/** - * @brief MCO output pin clock frequency. - */ -#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCOCLK STM32_MCODIVCLK - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 -#define STM32_MCOCLK (STM32_MCODIVCLK / 2) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 -#define STM32_MCOCLK (STM32_MCODIVCLK / 4) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 -#define STM32_MCOCLK (STM32_MCODIVCLK / 8) - -#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 -#define STM32_MCOCLK (STM32_MCODIVCLK / 16) - -#else -#error "invalid STM32_MCOPRE value specified" -#endif - -/** - * @brief RTC clock frequency. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 - -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK - -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK - -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) - -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief USART1 clock frequency. - */ -#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_USART1CLK STM32_PCLK2 - -#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK - -#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 -#define STM32_USART1CLK STM32_HSI16CLK - -#elif STM32_USART1SEL == STM32_USART1SEL_LSE -#define STM32_USART1CLK STM32_LSECLK - -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 clock frequency. - */ -#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART2CLK STM32_PCLK1 - -#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK - -#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 -#define STM32_USART2CLK STM32_HSI16CLK - -#elif STM32_USART2SEL == STM32_USART2SEL_LSE -#define STM32_USART2CLK STM32_LSECLK - -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 clock frequency. - */ -#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_USART3CLK STM32_PCLK1 - -#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK - -#elif STM32_USART3SEL == STM32_USART3SEL_HSI16 -#define STM32_USART3CLK STM32_HSI16CLK - -#elif STM32_USART3SEL == STM32_USART3SEL_LSE -#define STM32_USART3CLK STM32_LSECLK - -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief UART4 clock frequency. - */ -#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART4CLK STM32_PCLK1 - -#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK - -#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 -#define STM32_UART4CLK STM32_HSI16CLK - -#elif STM32_UART4SEL == STM32_UART4SEL_LSE -#define STM32_UART4CLK STM32_LSECLK - -#else -#error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 clock frequency. - */ -#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_UART5CLK STM32_PCLK1 - -#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK - -#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 -#define STM32_UART5CLK STM32_HSI16CLK - -#elif STM32_UART5SEL == STM32_UART5SEL_LSE -#define STM32_UART5CLK STM32_LSECLK - -#else -#error "invalid source selected for UART5 clock" -#endif - -/** - * @brief LPUART1 clock frequency. - */ -#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPUART1CLK STM32_PCLK1 - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK -#define STM32_LPUART1CLK STM32_SYSCLK - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 -#define STM32_LPUART1CLK STM32_HSI16CLK - -#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE -#define STM32_LPUART1CLK STM32_LSECLK - -#else -#error "invalid source selected for LPUART1 clock" -#endif - -/** - * @brief I2C1 clock frequency. - */ -#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C1CLK STM32_PCLK1 - -#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK - -#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 -#define STM32_I2C1CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 clock frequency. - */ -#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C2CLK STM32_PCLK1 - -#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK - -#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 -#define STM32_I2C2CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief I2C3 clock frequency. - */ -#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C3CLK STM32_PCLK1 - -#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK -#define STM32_I2C3CLK STM32_SYSCLK - -#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 -#define STM32_I2C3CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C3 clock" -#endif - -/** - * @brief I2C4 clock frequency. - */ -#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_I2C4CLK STM32_PCLK1 - -#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK -#define STM32_I2C4CLK STM32_SYSCLK - -#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 -#define STM32_I2C4CLK STM32_HSI16CLK - -#else -#error "invalid source selected for I2C4 clock" -#endif - -/** - * @brief LPTIM1 clock frequency. - */ -#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM1CLK STM32_PCLK1 - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI -#define STM32_LPTIM1CLK STM32_LSICLK - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 -#define STM32_LPTIM1CLK STM32_HSI16CLK - -#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE -#define STM32_LPTIM1CLK STM32_LSECLK - -#else -#error "invalid source selected for LPTIM1 clock" -#endif - -/** - * @brief LPTIM2 clock frequency. - */ -#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM2CLK STM32_PCLK1 - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI -#define STM32_LPTIM2CLK STM32_LSICLK - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 -#define STM32_LPTIM2CLK STM32_HSI16CLK - -#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE -#define STM32_LPTIM2CLK STM32_LSECLK - -#else -#error "invalid source selected for LPTIM2 clock" -#endif - -/** - * @brief LPTIM3 clock frequency. - */ -#if (STM32_LPTIM3SEL == STM32_LPTIM3SEL_PCLK1) || defined(__DOXYGEN__) -#define STM32_LPTIM3CLK STM32_PCLK1 - -#elif STM32_LPTIM3SEL == STM32_LPTIM3SEL_LSI -#define STM32_LPTIM3CLK STM32_LSICLK - -#elif STM32_LPTIM3SEL == STM32_LPTIM3SEL_HSI16 -#define STM32_LPTIM3CLK STM32_HSI16CLK - -#elif STM32_LPTIM3SEL == STM32_LPTIM3SEL_LSE -#define STM32_LPTIM3CLK STM32_LSECLK - -#else -#error "invalid source selected for LPTIM3 clock" -#endif - -/** - * @brief 48MHz clock frequency. - */ -#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) -#define STM32_48CLK STM32_HSI48CLK - -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 -#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) - -#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL -#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) - -#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI -#define STM32_48CLK STM32_MSICLK - -#else -#error "invalid source selected for 48CLK clock" -#endif - -/** - * @brief SAI1 clock frequency. - */ -#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2 -#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL -#define STM32_SAI1CLK STM32_PLL_P_CLKOUT - -#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK -#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ - -#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 -#define STM32_SAI1CLK STM32_HSI16CLK - -#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF -#define STM32_SAI1CLK 0 - -#else -#error "invalid source selected for SAI1 clock" -#endif - -/** - * @brief SAI2 clock frequency. - */ -#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__) -#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT - -#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2 -#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT - -#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL -#define STM32_SAI2CLK STM32_PLL_P_CLKOUT - -#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK -#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ - -#elif STM32_SAI2SEL == STM32_SAI2SEL_HSI16 -#define STM32_SAI2CLK STM32_HSI16CLK - -#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF -#define STM32_SAI2CLK 0 - -#else -#error "invalid source selected for SAI2 clock" -#endif - -/** - * @brief SDMMC clock frequency. - */ -#if (STM32_SDMMCSEL == STM32_SDMMCSEL_48CLK) || defined(__DOXYGEN__) -#define STM32_SDMMCCLK STM32_48CLK - -#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLLSAI3CLK -#define STM32_SDMMCCLK STM32_PLL_P_CLKOUT - -#else -#error "invalid source selected for SDMMC clock" -#endif - -/** - * @brief USB clock point. - */ -#define STM32_USBCLK STM32_48CLK - -/** - * @brief RNG clock point. - */ -#define STM32_RNGCLK STM32_48CLK - -/** - * @brief ADC clock frequency. - */ -#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__) -#define STM32_ADCCLK 0 - -#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1 -#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT - -#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK -#define STM32_ADCCLK STM32_SYSCLK - -#else -#error "invalid source selected for ADC clock" -#endif - -/** - * @brief DFSDM clock frequency. - */ -#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) -#define STM32_DFSDMCLK STM32_PCLK2 - -#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK -#define STM32_DFSDMCLK STM32_SYSCLK - -#else -#error "invalid source selected for DFSDM clock" -#endif - -/** - * @brief SDMMC frequency. - */ -#define STM32_SDMMC1CLK STM32_48CLK - -/** - * @brief OSPI clock frequency. - */ -#if (STM32_OSPISEL == STM32_OSPISEL_SYSCLK) || defined(__DOXYGEN__) -#define STM32_OSPICLK STM32_SYSCLK - -#elif STM32_OSPISEL == STM32_OSPISEL_MSI -#define STM32_OSPICLK STM32_MSICLK - -#elif STM32_OSPISEL == STM32_OSPISEL_48CLK -#define STM32_OSPICLK STM32_PLLSAI1_Q_CLKOUT - -#else -#error "invalid source selected for OSPI clock" -#endif - -/** - * @brief Clock of timers connected to APB1 - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Clock of timers connected to APB2. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS - -#else -#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS -#endif - -/** - * @brief Flash settings for MSI. - */ -#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS - -#elif STM32_MSICLK <= STM32_1WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS - -#elif STM32_MSICLK <= STM32_2WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS - -#elif STM32_MSICLK <= STM32_3WS_THRESHOLD -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS - -#else -#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "cache.h" -#include "mpu_v7m.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_exti.h" -#include "stm32_rcc.h" -#include "stm32_tim.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_LLD_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L5xx/hal_lld.h + * @brief STM32L5xx 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_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32L4R5xx, STM32L4R7xx, STM32L4R9xx. + * - STM32L4S5xx, STM32L4S7xx, STM32L4S9xx. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || \ + defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32L4+ Ultra Low Power" + +#elif defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define PLATFORM_NAME "STM32L4+ Ultra Low Power with Crypto" + +#else +#error "STM32L4+ device not specified" +#endif + +/** + * @brief Sub-family identifier. + */ +#if !defined(STM32L5XX) || defined(__DOXYGEN__) +#define STM32L5XX +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */ +#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR1 register bits definitions + * @{ + */ +#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */ +#define STM32_VOS_RANGE0 (0 << 9) /**< Core voltage 1.28 Volts. */ +#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */ +#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */ +/** @} */ + +/** + * @name PWR_CR2 register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */ +#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CR register bits definitions + * @{ + */ +#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */ +#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */ +#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */ +#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */ +#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */ +#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */ +#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */ +#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */ +#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */ +#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */ +#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */ +#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */ +#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW field mask. */ +#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */ +#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */ +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */ +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */ +#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */ +#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */ + +#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */ +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */ +#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */ +#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */ +#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */ + +#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */ +#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */ +#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */ +#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */ +#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */ +#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */ +#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */ + +/** + * @name RCC_PLLSAI1CFGR register bits definitions + * @{ + */ +#define STM32_PLLSAI1SRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSAI1SRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSAI1SRC_MSI (1 << 0) /**< PLL clock source is MSI. */ +#define STM32_PLLSAI1SRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSAI1SRC_HSE (3 << 0) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_PLLSAI2CFGR register bits definitions + * @{ + */ +#define STM32_PLLSAI2SRC_MASK (3 << 0) /**< PLL clock source mask. */ +#define STM32_PLLSAI2SRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */ +#define STM32_PLLSAI2SRC_MSI (1 << 0) /**< PLL clock source is MSI. */ +#define STM32_PLLSAI2SRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */ +#define STM32_PLLSAI2SRC_HSE (3 << 0) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CCIPR register bits definitions + * @{ + */ +#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */ +#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */ +#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */ +#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */ +#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */ + +#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */ +#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */ +#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */ +#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */ +#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */ + +#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */ +#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */ +#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */ +#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */ +#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */ + +#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */ +#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */ +#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */ +#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */ +#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */ + +#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */ +#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */ +#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */ +#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */ +#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */ + +#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */ +#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */ +#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */ +#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */ +#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */ + +#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */ +#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */ +#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */ + +#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */ +#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */ +#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */ +#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */ + +#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */ +#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */ +#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */ +#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */ + +#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */ +#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */ +#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */ +#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */ +#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */ + +#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */ +#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */ +#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */ +#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */ +#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */ + +#define STM32_LPTIM3SEL_MASK (3 << 22) /**< LPTIM3SEL mask. */ +#define STM32_LPTIM3SEL_PCLK1 (0 << 22) /**< LPTIM3 source is PCLK1. */ +#define STM32_LPTIM3SEL_LSI (1 << 22) /**< LPTIM3 source is LSI. */ +#define STM32_LPTIM3SEL_HSI16 (2 << 22) /**< LPTIM3 source is HSI16. */ +#define STM32_LPTIM3SEL_LSE (3 << 22) /**< LPTIM3 source is LSE. */ + +#define STM32_FDCANSEL_MASK (3 << 24) /**< FDCANSEL mask. */ +#define STM32_FDCANSEL_HSE (0 << 24) /**< FDCAN source is HSE. */ +#define STM32_FDCANSEL_PLL (1 << 24) /**< FDCAN source is PLL-Q. */ +#define STM32_FDCANSEL_PLLSAI1 (2 << 24) /**< FDCAN source is PLLSAI1-P. */ + +#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */ +#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */ +#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */ +#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */ +#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */ + +#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */ +#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */ +#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */ +#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */ +/** @} */ + +/** + * @name RCC_CCIPR2 register bits definitions + * @{ + */ +#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */ +#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */ +#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */ +#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */ + +#define STM32_DFSDMSEL_MASK (1 << 2) /**< DFSDMSEL mask. */ +#define STM32_DFSDMSEL_PCLK2 (0 << 2) /**< DFSDMSEL source is PCLK2. */ +#define STM32_DFSDMSEL_SYSCLK (1 << 2) /**< DFSDMSEL source is SYSCLK. */ + +#define STM32_ADFSDMSEL_MASK (3 << 3) /**< ADFSDMSEL mask. */ +#define STM32_ADFSDMSEL_SAI1CLK (0 << 3) /**< ADFSDMSEL source is + SAI1CLK. */ +#define STM32_ADFSDMSEL_HSI16 (1 << 3) /**< ADFSDMSEL source is HSI16. */ +#define STM32_ADFSDMSEL_MSI (2 << 3) /**< ADFSDMSEL source is MSI. */ + +#define STM32_SAI1SEL_MASK (7 << 5) /**< SAI1SEL mask. */ +#define STM32_SAI1SEL_PLLSAI1 (0 << 5) /**< SAI1 source is PLLSAI1CLK. */ +#define STM32_SAI1SEL_PLLSAI2 (1 << 5) /**< SAI1 source is PLLSAI2CLK. */ +#define STM32_SAI1SEL_PLL (2 << 5) /**< SAI1 source is PLLSAI3CLK */ +#define STM32_SAI1SEL_EXTCLK (3 << 5) /**< SAI1 source is external. */ +#define STM32_SAI1SEL_HSI16 (4 << 5) /**< SAI1 source is HSI16. */ +#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/ + +#define STM32_SAI2SEL_MASK (7 << 8) /**< SAI2SEL mask. */ +#define STM32_SAI2SEL_PLLSAI1 (0 << 8) /**< SAI2 source is PLLSAI1CLK. */ +#define STM32_SAI2SEL_PLLSAI2 (1 << 8) /**< SAI2 source is PLLSAI2CLK. */ +#define STM32_SAI2SEL_PLL (2 << 8) /**< SAI2 source is PLLSAI3CLK */ +#define STM32_SAI2SEL_EXTCLK (3 << 8) /**< SAI2 source is external. */ +#define STM32_SAI2SEL_HSI16 (4 << 8) /**< SAI2 source is HSI16. */ +#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/ + +#define STM32_SDMMCSEL_MASK (1 << 14) /**< SDMMCSEL mask. */ +#define STM32_SDMMCSEL_48CLK (0 << 14) /**< SDMMCSEL source is 48CLK. */ +#define STM32_SDMMCSEL_PLL (1 << 14) /**< SDMMCSEL source is + PLLSAI3CLK. */ + +#define STM32_OSPISEL_MASK (3 << 20) /**< OSPISEL mask. */ +#define STM32_OSPISEL_SYSCLK (0 << 20) /**< OSPI source is SYSCLK. */ +#define STM32_OSPISEL_MSI (1 << 20) /**< OSPI source is MSI. */ +#define STM32_OSPISEL_48CLK (2 << 20) /**< OSPI source is 48CLK. */ +/** @} */ + +/** + * @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. */ + +#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */ +#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */ +#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */ +#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */ +/** @} */ + +/** + * @name RCC_CSR register bits definitions + * @{ + */ +#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */ +#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */ +#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */ +#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */ +#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_RANGE1 +#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 HSI16 clock source. + */ +#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI16_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSI48 clock source. + */ +#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI48_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Number of times to busy-loop waiting for LSE clock source. + * @note The default value of 0 disables this behavior. + * @note See also FOME_STM32_LSE_WAIT_MAX_RTCSEL. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX 0 +#endif + +/** + * @brief Fallback RTC clock source if stopped waiting for LSE clock source. + * @note If waiting for the LSE clock source times out due to + * FOME_STM32_LSE_WAIT_MAX, this allows the RTC clock source to + * fallback to another. + */ +#if !defined(FOME_STM32_LSE_WAIT_MAX_RTCSEL) || defined(__DOXYGEN__) +#define FOME_STM32_LSE_WAIT_MAX_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief Enables or disables the MSI PLL on LSE clock source. + */ +#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__) +#define STM32_MSIPLL_ENABLED FALSE +#endif + +/** + * @brief MSI frequency setting. + */ +#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__) +#define STM32_MSIRANGE STM32_MSIRANGE_4M +#endif + +/** + * @brief MSI frequency setting after standby. + */ +#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__) +#define STM32_MSISRANGE STM32_MSISRANGE_4M +#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 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @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 internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_MSI +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 1 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 8..127. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 60 +#endif + +/** + * @brief PLLPDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLPDIV_VALUE 0 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 7 +#endif + +/** + * @brief PLLQ divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 4 +#endif + +/** + * @brief PLLR divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLR_VALUE 2 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#endif + +/** + * @brief STOPWUCK clock setting. + */ +#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__) +#define STM32_STOPWUCK STM32_STOPWUCK_MSI +#endif + +/** + * @brief MCO clock source. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief MCO divider setting. + */ +#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__) +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#endif + +/** + * @brief LSCO clock source. + */ +#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__) +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#endif + +/** + * @brief Clock source for the PLLSAL1. + */ +#if !defined(STM32_PLLSAI1SRC) || defined(__DOXYGEN__) +#define STM32_PLLSAI1SRC STM32_PLLSAI1SRC_MSI +#endif + +/** + * @brief PLLSAI1M divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSAI1M_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1M_VALUE 1 +#endif + +/** + * @brief PLLSAI1N multiplier value. + * @note The allowed values are 8..127. + */ +#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1N_VALUE 72 +#endif + +/** + * @brief PLLSAI1PDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1PDIV_VALUE 6 +#endif + +/** + * @brief PLLSAI1P divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1P_VALUE 7 +#endif + +/** + * @brief PLLSAI1Q divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1Q_VALUE 6 +#endif + +/** + * @brief PLLSAI1R divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1R_VALUE 6 +#endif + +/** + * @brief Clock source for the PLLSAL2. + */ +#if !defined(STM32_PLLSAI2SRC) || defined(__DOXYGEN__) +#define STM32_PLLSAI2SRC STM32_PLLSAI2SRC_MSI +#endif + +/** + * @brief PLLSAI2M divider value. + * @note The allowed values are 1..16. + * @note The default value is calculated for a 120MHz system clock from + * the internal 4MHz MSI clock. + */ +#if !defined(STM32_PLLSAI2M_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2M_VALUE 1 +#endif + +/** + * @brief PLLSAI2N multiplier value. + * @note The allowed values are 8..127. + */ +#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2N_VALUE 72 +#endif + +/** + * @brief PLLSAI2PDIV divider value or zero if disabled. + * @note The allowed values are 0, 2..31. + */ +#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2PDIV_VALUE 6 +#endif + +/** + * @brief PLLSAI2P divider value. + * @note The allowed values are 7, 17. + */ +#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2P_VALUE 7 +#endif + +/** + * @brief PLLSAI2Q divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI2Q_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2Q_VALUE 6 +#endif + +/** + * @brief PLLSAI2R divider value. + * @note The allowed values are 2, 4, 6, 8. + */ +#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2R_VALUE 6 +#endif + +/** + * @brief PLLSAI2DIVR value. + */ +#if !defined(STM32_PLLSAI2DIVR) || defined(__DOXYGEN__) +#define STM32_PLLSAI2DIVR STM32_PLLSAI2DIVR_DIV16 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__) +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__) +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__) +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__) +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__) +#define STM32_UART5SEL STM32_UART5SEL_SYSCLK +#endif + +/** + * @brief LPUART1 clock source. + */ +#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__) +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__) +#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__) +#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK +#endif + +/** + * @brief I2C3 clock source. + */ +#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__) +#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK +#endif + +/** + * @brief I2C4 clock source. + */ +#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__) +#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK +#endif + +/** + * @brief LPTIM1 clock source. + */ +#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#endif + +/** + * @brief LPTIM2 clock source. + */ +#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 +#endif + +/** + * @brief LPTIM3 clock source. + */ +#if !defined(STM32_LPTIM3SEL) || defined(__DOXYGEN__) +#define STM32_LPTIM3SEL STM32_LPTIM3SEL_PCLK1 +#endif + +/** + * @brief FDCAN value (48MHz clock source). + */ +#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__) +#define STM32_FDCANSEL STM32_FDCANSEL_PLL +#endif + +/** + * @brief CLK48SEL value (48MHz clock source). + */ +#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__) +#define STM32_CLK48SEL STM32_CLK48SEL_PLL +#endif + +/** + * @brief ADCSEL value (ADCs clock source). + */ +#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__) +#define STM32_ADCSEL STM32_ADCSEL_SYSCLK +#endif + +/** + * @brief DFSDMSEL value (DFSDM clock source). + */ +#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__) +#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 +#endif + +/** + * @brief ADFSDMSEL value (DFSDM clock source). + */ +#if !defined(STM32_ADFSDMSEL) || defined(__DOXYGEN__) +#define STM32_ADFSDMSEL STM32_ADFSDMSEL_SAI1CLK +#endif + +/** + * @brief SAI1SEL value (SAI1 clock source). + */ +#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__) +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#endif + +/** + * @brief SAI2SEL value (SAI2 clock source). + */ +#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__) +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#endif + +/** + * @brief SDMMC value (SDMMC clock source). + */ +#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__) +#define STM32_SDMMCSEL STM32_SDMMCSEL_48CLK +#endif + +/** + * @brief OSPISEL value (OSPISEL clock source). + */ +#if !defined(STM32_OSPISEL) || defined(__DOXYGEN__) +#define STM32_OSPISEL STM32_OSPISEL_SYSCLK +#endif + +/** + * @brief RTC/LCD clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32L5xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L5xx_MCUCONF not defined" +#endif + +#if defined(STM32L5YYxx) && !defined(STM32L5YY_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32L5YY_MCUCONF not defined" + +#endif + +/* + * Board files sanity checks. + */ +#if !defined(STM32_LSECLK) +#error "STM32_LSECLK not defined in board.h" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined in board.h" +#endif + +#if !defined(STM32_HSECLK) +#error "STM32_HSECLK not defined in board.h" +#endif + +/* Voltage related limits.*/ +#if (STM32_VOS == STM32_VOS_RANGE0) || defined(__DOXYGEN__) +/** + * @name System Limits + * @{ + */ +/** + * @brief Maximum SYSCLK clock frequency. + */ +#define STM32_SYSCLK_MAX 110000000 + +/** + * @brief Maximum HSE clock frequency at current voltage setting. + */ +#define STM32_HSECLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MAX 48000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 4000000 + +/** + * @brief Minimum HSE clock frequency using an external source. + */ +#define STM32_HSECLK_BYP_MIN 8000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 32768 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_BYP_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 16000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 2660000 + +/** + * @brief Maximum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MAX 344000000 + +/** + * @brief Minimum VCO clock frequency at current voltage setting. + */ +#define STM32_PLLVCO_MIN 64000000 + +/** + * @brief Maximum PLL-P output clock frequency. + */ +#define STM32_PLLP_MAX 110000000 + +/** + * @brief Minimum PLL-P output clock frequency. + */ +#define STM32_PLLP_MIN 2064500 + +/** + * @brief Maximum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MAX 110000000 + +/** + * @brief Minimum PLL-Q output clock frequency. + */ +#define STM32_PLLQ_MIN 8000000 + +/** + * @brief Maximum PLL-R output clock frequency. + */ +#define STM32_PLLR_MAX 110000000 + +/** + * @brief Minimum PLL-R output clock frequency. + */ +#define STM32_PLLR_MIN 8000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 110000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 110000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 80000000 +/** @} */ + +/** + * @name Flash Wait states + * @{ + */ +#define STM32_0WS_THRESHOLD 20000000 +#define STM32_1WS_THRESHOLD 40000000 +#define STM32_2WS_THRESHOLD 60000000 +#define STM32_3WS_THRESHOLD 80000000 +#define STM32_4WS_THRESHOLD 100000000 +#define STM32_5WS_THRESHOLD 110000000 +/** @} */ + +#elif STM32_VOS == STM32_VOS_RANGE1 +#define STM32_SYSCLK_MAX 80000000 +#define STM32_HSECLK_MAX 48000000 +#define STM32_HSECLK_BYP_MAX 48000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 8000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_LSECLK_BYP_MIN 32768 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MIN 2660000 +#define STM32_PLLVCO_MAX 344000000 +#define STM32_PLLVCO_MIN 64000000 +#define STM32_PLLP_MAX 110000000 +#define STM32_PLLP_MIN 2064500 +#define STM32_PLLQ_MAX 110000000 +#define STM32_PLLQ_MIN 8000000 +#define STM32_PLLR_MAX 110000000 +#define STM32_PLLR_MIN 8000000 +#define STM32_PCLK1_MAX 80000000 +#define STM32_PCLK2_MAX 80000000 +#define STM32_ADCCLK_MAX 80000000 + +#define STM32_0WS_THRESHOLD 20000000 +#define STM32_1WS_THRESHOLD 40000000 +#define STM32_2WS_THRESHOLD 60000000 +#define STM32_3WS_THRESHOLD 80000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 + +#elif STM32_VOS == STM32_VOS_RANGE2 +#define STM32_SYSCLK_MAX 26000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_BYP_MAX 26000000 +#define STM32_HSECLK_MIN 4000000 +#define STM32_HSECLK_BYP_MIN 8000000 +#define STM32_LSECLK_MAX 32768 +#define STM32_LSECLK_BYP_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_LSECLK_BYP_MIN 32768 +#define STM32_PLLIN_MAX 16000000 +#define STM32_PLLIN_MIN 2660000 +#define STM32_PLLVCO_MAX 128000000 +#define STM32_PLLVCO_MIN 64000000 +#define STM32_PLLP_MAX 26000000 +#define STM32_PLLP_MIN 2064500 +#define STM32_PLLQ_MAX 26000000 +#define STM32_PLLQ_MIN 8000000 +#define STM32_PLLR_MAX 26000000 +#define STM32_PLLR_MIN 8000000 +#define STM32_PCLK1_MAX 26000000 +#define STM32_PCLK2_MAX 26000000 +#define STM32_ADCCLK_MAX 26000000 + +#define STM32_0WS_THRESHOLD 8000000 +#define STM32_1WS_THRESHOLD 16000000 +#define STM32_2WS_THRESHOLD 26000000 +#define STM32_3WS_THRESHOLD 0 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 + +#else + #error "invalid STM32_VOS value specified" +#endif + +/** + * @brief MSI frequency. + */ +#if STM32_MSIRANGE == STM32_MSIRANGE_100K + #define STM32_MSICLK 100000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_200K + #define STM32_MSICLK 200000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_400K + #define STM32_MSICLK 400000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_800K + #define STM32_MSICLK 800000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_1M + #define STM32_MSICLK 1000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_2M + #define STM32_MSICLK 2000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_4M + #define STM32_MSICLK 4000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_8M + #define STM32_MSICLK 8000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_16M + #define STM32_MSICLK 16000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_24M + #define STM32_MSICLK 24000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_32M + #define STM32_MSICLK 32000000 +#elif STM32_MSIRANGE == STM32_MSIRANGE_48M + #define STM32_MSICLK 48000000 +#else + #error "invalid STM32_MSIRANGE value specified" +#endif + +/** + * @brief MSIS frequency. + */ +#if STM32_MSISRANGE == STM32_MSISRANGE_1M + #define STM32_MSISCLK 1000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_2M + #define STM32_MSISCLK 2000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_4M + #define STM32_MSISCLK 4000000 +#elif STM32_MSISRANGE == STM32_MSISRANGE_8M + #define STM32_MSISCLK 8000000 +#else + #error "invalid STM32_MSISRANGE value specified" +#endif + +/* + * HSI16 related checks. + */ +#if STM32_HSI16_ENABLED +#else /* !STM32_HSI16_ENABLED */ + + #if STM32_SW == STM32_SW_HSI16 + #error "HSI16 not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16) + #error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + /* MCO-related checks.*/ + #if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16)) + #error "HSI16 not enabled, required by STM32_MCOSEL" + #endif + + /* SAI1-related checks.*/ + #if STM32_SAI1SEL == STM32_SAI1SEL_HSI16 + #error "HSI16 not enabled, required by STM32_SAI1SEL" + #endif + + #if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16) + #error "HSI16 not enabled, required by STM32_SAI1SEL" + #endif + + #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) && \ + (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSI16) + #error "HSI16 not enabled, required by STM32_PLLSAI1SRC" + #endif + + #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) && \ + (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSI16) + #error "HSI16 not enabled, required by STM32_PLLSAI2SRC" + #endif + + /* SAI2-related checks.*/ + #if STM32_SAI2SEL == STM32_SAI12SEL_HSI16 + #error "HSI16 not enabled, required by STM32_SAI2SEL" + #endif + + #if (STM32_SAI2SEL == STM32_SAI2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI16) + #error "HSI16 not enabled, required by STM32_SAI2SEL" + #endif + + #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) && \ + (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSI16) + #error "HSI16 not enabled, required by STM32_PLLSAI1SRC" + #endif + + #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) && \ + (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSI16) + #error "HSI16 not enabled, required by STM32_PLLSAI2SRC" + #endif + + /* USART/UART-related checks.*/ + #if (STM32_USART1SEL == STM32_USART1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_USART1SEL" + #endif + #if (STM32_USART2SEL == STM32_USART2SEL_HSI16) + #error "HSI16 not enabled, required by STM32_USART2SEL" + #endif + #if (STM32_USART3SEL == STM32_USART3SEL_HSI16) + #error "HSI16 not enabled, required by STM32_USART3SEL" + #endif + #if (STM32_UART4SEL == STM32_UART4SEL_HSI16) + #error "HSI16 not enabled, required by STM32_UART4SEL" + #endif + #if (STM32_UART5SEL == STM32_UART5SEL_HSI16) + #error "HSI16 not enabled, required by STM32_UART5SEL" + #endif + #if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16) + #error "HSI16 not enabled, required by STM32_LPUART1SEL" + #endif + + /* I2C-related checks.*/ + #if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16) + #error "HSI16 not enabled, required by I2C1SEL" + #endif + #if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16) + #error "HSI16 not enabled, required by I2C2SEL" + #endif + #if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16) + #error "HSI16 not enabled, required by I2C3SEL" + #endif + #if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16) + #error "HSI16 not enabled, required by I2C4SEL" + #endif + + /* LPTIM-related checks.*/ + #if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16) + #error "HSI16 not enabled, required by LPTIM1SEL" + #endif + #if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16) + #error "HSI16 not enabled, required by LPTIM2SEL" + #endif + + #if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16) + #error "HSI16 not enabled, required by STM32_STOPWUCK" + #endif + +#endif /* !STM32_HSI16_ENABLED */ + +#if STM32_HSI48_ENABLED +#else /* !STM32_HSI48_ENABLED */ + + #if STM32_MCOSEL == STM32_MCOSEL_HSI48 + #error "HSI48 not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_CLK48SEL == STM32_CLK48SEL_HSI48 + #error "HSI48 not enabled, required by STM32_CLK48SEL" + #endif + +#endif /* !STM32_HSI48_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + + #if STM32_HSECLK == 0 + #error "HSE frequency not defined" + #else /* STM32_HSECLK != 0 */ + #if defined(STM32_HSE_BYPASS) + #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)" + #endif + #else /* !defined(STM32_HSE_BYPASS) */ + #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) + #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" + #endif + #endif /* !defined(STM32_HSE_BYPASS) */ + #endif /* STM32_HSECLK != 0 */ + +#else /* !STM32_HSE_ENABLED */ + + #if STM32_SW == STM32_SW_HSE + #error "HSE not enabled, required by STM32_SW" + #endif + + #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" + #endif + + /* MCO-related checks.*/ + #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) + #error "HSE not enabled, required by STM32_MCOSEL" + #endif + + /* SAI1-related checks.*/ + #if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SAI1SEL" + #endif + + #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) && \ + (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSE) + #error "HSE not enabled, required by STM32_PLLSAI1SRC" + #endif + + #if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) && \ + (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSE) + #error "HSE not enabled, required by STM32_PLLSAI2SRC" + #endif + + /* SAI2-related checks.*/ + #if (STM32_SAI2SEL == STM32_SAI2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) + #error "HSE not enabled, required by STM32_SAI2SEL" + #endif + + #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) && \ + (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSE) + #error "HSE not enabled, required by STM32_PLLSAI1SRC" + #endif + + #if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) && \ + (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSE) + #error "HSE not enabled, required by STM32_PLLSAI2SRC" + #endif + + /* RTC-related checks.*/ + #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV + #error "HSE not enabled, required by STM32_RTCSEL" + #endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + + #if STM32_RTCSEL == STM32_RTCSEL_LSI + #error "LSI not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSI + #error "LSI not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSI + #error "LSI not enabled, required by STM32_LSCOSEL" + #endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + + #if (STM32_LSECLK == 0) + #error "LSE frequency not defined" + #endif + + #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) + #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" + #endif + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL) + #error "FOME_STM32_LSE_WAIT_MAX_RTCSEL is same as STM32_RTCSEL" + #endif + +#else /* !STM32_LSE_ENABLED */ + + #if (FOME_STM32_LSE_WAIT_MAX > 0) && (FOME_STM32_LSE_WAIT_MAX_RTCSEL == STM32_RTCSEL_LSE) + #error "LSE not enabled, required by FOME_STM32_LSE_WAIT_MAX_RTCSEL" + #endif + + #if STM32_RTCSEL == STM32_RTCSEL_LSE + #error "LSE not enabled, required by STM32_RTCSEL" + #endif + + #if STM32_MCOSEL == STM32_MCOSEL_LSE + #error "LSE not enabled, required by STM32_MCOSEL" + #endif + + #if STM32_LSCOSEL == STM32_LSCOSEL_LSE + #error "LSE not enabled, required by STM32_LSCOSEL" + #endif + + #if STM32_MSIPLL_ENABLED == TRUE + #error "LSE not enabled, required by STM32_MSIPLL_ENABLED" + #endif + +#endif /* !STM32_LSE_ENABLED */ + +/* + * MSI related checks. + */ +#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED + #warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED" +#endif + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \ + defined(__DOXYGEN__) + #define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4) +#else + #error "invalid STM32_PLLM_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) + #define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_MSI + #define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_HSI16 + #define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE) + +#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK + #define STM32_PLLCLKIN 0 + +#else + #error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLL input frequency range check. + */ +#if (STM32_PLLCLKIN != 0) && \ + ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)) + #error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ + defined(__DOXYGEN__) + + #if STM32_PLLCLKIN == 0 + #error "PLL activation required but no PLL clock selected" + #endif + +/** + * @brief PLL activation flag. + */ + #define STM32_ACTIVATE_PLL TRUE +#else + #define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 8) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLP (0 << 17) + +#elif STM32_PLLP_VALUE == 17 +#define STM32_PLLP (1 << 17) + +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLQ (0 << 21) + +#elif STM32_PLLQ_VALUE == 4 +#define STM32_PLLQ (1 << 21) + +#elif STM32_PLLQ_VALUE == 6 +#define STM32_PLLQ (2 << 21) + +#elif STM32_PLLQ_VALUE == 8 +#define STM32_PLLQ (3 << 21) + +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief STM32_PLLR field. + */ +#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLR (0 << 25) + +#elif STM32_PLLR_VALUE == 4 +#define STM32_PLLR (1 << 25) + +#elif STM32_PLLR_VALUE == 6 +#define STM32_PLLR (2 << 25) + +#elif STM32_PLLR_VALUE == 8 +#define STM32_PLLR (3 << 25) + +#else +#error "invalid STM32_PLLR_VALUE value specified" +#endif + +/** + * @brief STM32_PLLPDIV field. + */ +#if (STM32_PLLPDIV_VALUE == 0) || \ + ((STM32_PLLPDIV_VALUE != 1) && (STM32_PLLPDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27) +#else +#error "invalid STM32_PLLPDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLPEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \ + defined(__DOXYGEN__) +#define STM32_PLLPEN (1 << 16) +#else +#define STM32_PLLPEN (0 << 16) +#endif + +/** + * @brief STM32_PLLQEN field. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__) +#define STM32_PLLQEN (1 << 20) +#else +#define STM32_PLLQEN (0 << 20) +#endif + +/** + * @brief STM32_PLLREN field. + */ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLL) || \ + defined(__DOXYGEN__) +#define STM32_PLLREN (1 << 24) +#else +#define STM32_PLLREN (0 << 24) +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL P output clock frequency. + */ +#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) +#else +#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE) +#endif + +/** + * @brief PLL Q output clock frequency. + */ +#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE) + +/** + * @brief PLL R output clock frequency. + */ +#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE) + +/* + * PLL-P output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLL-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLL-R output frequency range check. + */ +#if STM32_ACTIVATE_PLL && \ + ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_MSICLK + +#elif (STM32_SW == STM32_SW_MSI) +#define STM32_SYSCLK STM32_MSICLK + +#elif (STM32_SW == STM32_SW_HSI16) +#define STM32_SYSCLK STM32_HSI16CLK + +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK + +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLL_R_CLKOUT + +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) + +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) + +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) + +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) + +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) + +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) + +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) + +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) + +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) + +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) + +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) + +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) + +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief STM32_PLLSAI1M field. + */ +#if ((STM32_PLLSAI1M_VALUE >= 1) && (STM32_PLLSAI1M_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1M ((STM32_PLLSAI1M_VALUE - 1) << 4) +#else +#error "invalid STM32_PLLSAI1M_VALUE value specified" +#endif + +/** + * @brief PLLSAI1 input clock frequency. + */ +#if (STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSAI1CLKIN (STM32_HSECLK / STM32_PLLSAI1M_VALUE) + +#elif STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_MSI +#define STM32_PLLSAI1CLKIN (STM32_MSICLK / STM32_PLLSAI1M_VALUE) + +#elif STM32_PLLSAI1SRC == STM32_PLLSAI1SRC_HSI16 +#define STM32_PLLSAI1CLKIN (STM32_HSI16CLK / STM32_PLLSAI1M_VALUE) + +#elif STM32_PLLSSAI1RC == STM32_PLLSAI1SRC_NOCLOCK +#define STM32_PLLSAI1CLKIN 0 + +#else +#error "invalid STM32_PLLSAI1SRC value specified" +#endif + +/* + * PLLSAI1 input frequency range check. + */ +#if (STM32_PLLSAI1CLKIN != 0) && \ + ((STM32_PLLSAI1CLKIN < STM32_PLLIN_MIN) || \ + (STM32_PLLSAI1CLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLSAI1CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLLSAI1 enable check. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \ + (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ + defined(__DOXYGEN__) + +#if STM32_PLLSAI1CLKIN == 0 +#error "PLLSAI1 activation required but no PLL clock selected" +#endif + +/** + * @brief PLLSAI1 activation flag. + */ +#define STM32_ACTIVATE_PLLSAI1 TRUE +#else +#define STM32_ACTIVATE_PLLSAI1 FALSE +#endif + +/** + * @brief STM32_PLLSAI1N field. + */ +#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 127)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8) +#else +#error "invalid STM32_PLLSAI1N_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1P field. + */ +#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLSAI1P (0 << 17) + +#elif STM32_PLLSAI1P_VALUE == 17 +#define STM32_PLLSAI1P (1 << 17) + +#else +#error "invalid STM32_PLLSAI1P_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1Q field. + */ +#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI1Q (0 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 4 +#define STM32_PLLSAI1Q (1 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 6 +#define STM32_PLLSAI1Q (2 << 21) + +#elif STM32_PLLSAI1Q_VALUE == 8 +#define STM32_PLLSAI1Q (3 << 21) + +#else +#error "invalid STM32_PLLSAI1Q_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1R field. + */ +#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI1R (0 << 25) + +#elif STM32_PLLSAI1R_VALUE == 4 +#define STM32_PLLSAI1R (1 << 25) + +#elif STM32_PLLSAI1R_VALUE == 6 +#define STM32_PLLSAI1R (2 << 25) + +#elif STM32_PLLSAI1R_VALUE == 8 +#define STM32_PLLSAI1R (3 << 25) + +#else +#error "invalid STM32_PLLSAI1R_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1PDIV field. + */ +#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27) +#else +#error "invalid STM32_PLLSAI1PDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI1PEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI1PEN (1 << 16) +#else +#define STM32_PLLSAI1PEN (0 << 16) +#endif + +/** + * @brief STM32_PLLSAI1QEN field. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_PLLSAI1QEN (1 << 20) +#else +#define STM32_PLLSAI1QEN (0 << 20) +#endif + +/** + * @brief STM32_PLLSAI1REN field. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_PLLSAI1REN (1 << 24) +#else +#define STM32_PLLSAI1REN (0 << 24) +#endif + +/** + * @brief PLLSAI1 VCO frequency. + */ +#define STM32_PLLSAI1VCO (STM32_PLLSAI1CLKIN * STM32_PLLSAI1N_VALUE) + +/* + * PLLSAI1 VCO frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI1-P output clock frequency. + */ +#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE) +#else +#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE) +#endif + +/** + * @brief PLLSAI1-Q output clock frequency. + */ +#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) + +/** + * @brief PLLSAI1-R output clock frequency. + */ +#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE) + +/* + * PLLSAI1-P output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLLSAI1-Q output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX)) +#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)" +#endif + +/* + * PLLSAI1-R output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI1 && \ + ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief STM32_PLLSAI2M field. + */ +#if ((STM32_PLLSAI2M_VALUE >= 1) && (STM32_PLLSAI2M_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2M ((STM32_PLLSAI2M_VALUE - 1) << 4) +#else +#error "invalid STM32_PLLSAI2M_VALUE value specified" +#endif + +/** + * @brief PLLSAI2 input clock frequency. + */ +#if (STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLSAI2CLKIN (STM32_HSECLK / STM32_PLLSAI2M_VALUE) + +#elif STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_MSI +#define STM32_PLLSAI2CLKIN (STM32_MSICLK / STM32_PLLSAI2M_VALUE) + +#elif STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_HSI16 +#define STM32_PLLSAI2CLKIN (STM32_HSI16CLK / STM32_PLLSAI2M_VALUE) + +#elif STM32_PLLSAI2SRC == STM32_PLLSAI2SRC_NOCLOCK +#define STM32_PLLSAI2CLKIN 0 + +#else +#error "invalid STM32_PLLSAI2SRC value specified" +#endif + +/* + * PLLSAI2 input frequency range check. + */ +#if (STM32_PLLSAI2CLKIN != 0) && \ + ((STM32_PLLSAI2CLKIN < STM32_PLLIN_MIN) || \ + (STM32_PLLSAI2CLKIN > STM32_PLLIN_MAX)) +#error "STM32_PLLSAI2CLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLLSAI2 enable check. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ + (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \ + defined(__DOXYGEN__) + +#if STM32_PLLSAI2CLKIN == 0 +#error "PLLSAI2 activation required but no PLL clock selected" +#endif + +/** + * @brief PLLSAI2 activation flag. + */ +#define STM32_ACTIVATE_PLLSAI2 TRUE +#else +#define STM32_ACTIVATE_PLLSAI2 FALSE +#endif + +/** + * @brief STM32_PLLSAI2N field. + */ +#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 127)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8) +#else +#error "invalid STM32_PLLSAI2N_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2P field. + */ +#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__) +#define STM32_PLLSAI2P (0 << 17) + +#elif STM32_PLLSAI2P_VALUE == 17 +#define STM32_PLLSAI2P (1 << 17) + +#else +#error "invalid STM32_PLLSAI2P_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2R field. + */ +#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLSAI2R (0 << 25) + +#elif STM32_PLLSAI2R_VALUE == 4 +#define STM32_PLLSAI2R (1 << 25) + +#elif STM32_PLLSAI2R_VALUE == 6 +#define STM32_PLLSAI2R (2 << 25) + +#elif STM32_PLLSAI2R_VALUE == 8 +#define STM32_PLLSAI2R (3 << 25) + +#else +#error "invalid STM32_PLLSAI2R_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2PDIV field. + */ +#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27) +#else +#error "invalid STM32_PLLSAI2PDIV_VALUE value specified" +#endif + +/** + * @brief STM32_PLLSAI2PEN field. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \ + defined(__DOXYGEN__) +#define STM32_PLLSAI2PEN (1 << 16) +#else +#define STM32_PLLSAI2PEN (0 << 16) +#endif + +/** + * @brief STM32_PLLSAI2REN field. + * @note Always enabled. + * @note It should depend on some condition. + */ +#define STM32_PLLSAI2REN (1 << 24) + +/** + * @brief PLLSAI2 VCO frequency. + */ +#define STM32_PLLSAI2VCO (STM32_PLLSAI2CLKIN * STM32_PLLSAI2N_VALUE) + +/* + * PLLSAI2 VCO frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX)) +#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLSAI2-P output clock frequency. + */ +#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__) +#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE) +#else +#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE) +#endif + +/** + * @brief PLLSAI2-R output clock frequency. + */ +#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE) + +/* + * PLLSAI2-P output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX)) +#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)" +#endif + +/* + * PLLSAI2-R output frequency range check. + */ +#if STM32_ACTIVATE_PLLSAI2 && \ + ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX)) +#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)" +#endif + +/** + * @brief MCO divider clock frequency. + */ +#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_MCODIVCLK 0 + +#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK +#define STM32_MCODIVCLK STM32_SYSCLK + +#elif STM32_MCOSEL == STM32_MCOSEL_MSI +#define STM32_MCODIVCLK STM32_MSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI16 +#define STM32_MCODIVCLK STM32_HSI16CLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSE +#define STM32_MCODIVCLK STM32_HSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_PLL +#define STM32_MCODIVCLK STM32_PLL_P_CLKOUT + +#elif STM32_MCOSEL == STM32_MCOSEL_LSI +#define STM32_MCODIVCLK STM32_LSICLK + +#elif STM32_MCOSEL == STM32_MCOSEL_LSE +#define STM32_MCODIVCLK STM32_LSECLK + +#elif STM32_MCOSEL == STM32_MCOSEL_HSI48 +#define STM32_MCODIVCLK STM32_HSI48CLK + +#else +#error "invalid STM32_MCOSEL value specified" +#endif + +/** + * @brief MCO output pin clock frequency. + */ +#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCOCLK STM32_MCODIVCLK + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV2 +#define STM32_MCOCLK (STM32_MCODIVCLK / 2) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV4 +#define STM32_MCOCLK (STM32_MCODIVCLK / 4) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV8 +#define STM32_MCOCLK (STM32_MCODIVCLK / 8) + +#elif STM32_MCOPRE == STM32_MCOPRE_DIV16 +#define STM32_MCOCLK (STM32_MCODIVCLK / 16) + +#else +#error "invalid STM32_MCOPRE value specified" +#endif + +/** + * @brief RTC clock frequency. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 + +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK + +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK + +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) + +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief USART1 clock frequency. + */ +#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_USART1CLK STM32_PCLK2 + +#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK + +#elif STM32_USART1SEL == STM32_USART1SEL_HSI16 +#define STM32_USART1CLK STM32_HSI16CLK + +#elif STM32_USART1SEL == STM32_USART1SEL_LSE +#define STM32_USART1CLK STM32_LSECLK + +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 clock frequency. + */ +#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART2CLK STM32_PCLK1 + +#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK + +#elif STM32_USART2SEL == STM32_USART2SEL_HSI16 +#define STM32_USART2CLK STM32_HSI16CLK + +#elif STM32_USART2SEL == STM32_USART2SEL_LSE +#define STM32_USART2CLK STM32_LSECLK + +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 clock frequency. + */ +#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_USART3CLK STM32_PCLK1 + +#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK + +#elif STM32_USART3SEL == STM32_USART3SEL_HSI16 +#define STM32_USART3CLK STM32_HSI16CLK + +#elif STM32_USART3SEL == STM32_USART3SEL_LSE +#define STM32_USART3CLK STM32_LSECLK + +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief UART4 clock frequency. + */ +#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART4CLK STM32_PCLK1 + +#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK +#define STM32_UART4CLK STM32_SYSCLK + +#elif STM32_UART4SEL == STM32_UART4SEL_HSI16 +#define STM32_UART4CLK STM32_HSI16CLK + +#elif STM32_UART4SEL == STM32_UART4SEL_LSE +#define STM32_UART4CLK STM32_LSECLK + +#else +#error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 clock frequency. + */ +#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_UART5CLK STM32_PCLK1 + +#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK +#define STM32_UART5CLK STM32_SYSCLK + +#elif STM32_UART5SEL == STM32_UART5SEL_HSI16 +#define STM32_UART5CLK STM32_HSI16CLK + +#elif STM32_UART5SEL == STM32_UART5SEL_LSE +#define STM32_UART5CLK STM32_LSECLK + +#else +#error "invalid source selected for UART5 clock" +#endif + +/** + * @brief LPUART1 clock frequency. + */ +#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPUART1CLK STM32_PCLK1 + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK +#define STM32_LPUART1CLK STM32_SYSCLK + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16 +#define STM32_LPUART1CLK STM32_HSI16CLK + +#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE +#define STM32_LPUART1CLK STM32_LSECLK + +#else +#error "invalid source selected for LPUART1 clock" +#endif + +/** + * @brief I2C1 clock frequency. + */ +#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C1CLK STM32_PCLK1 + +#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK + +#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16 +#define STM32_I2C1CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 clock frequency. + */ +#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C2CLK STM32_PCLK1 + +#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK + +#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16 +#define STM32_I2C2CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief I2C3 clock frequency. + */ +#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C3CLK STM32_PCLK1 + +#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK +#define STM32_I2C3CLK STM32_SYSCLK + +#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16 +#define STM32_I2C3CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C3 clock" +#endif + +/** + * @brief I2C4 clock frequency. + */ +#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_I2C4CLK STM32_PCLK1 + +#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK +#define STM32_I2C4CLK STM32_SYSCLK + +#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16 +#define STM32_I2C4CLK STM32_HSI16CLK + +#else +#error "invalid source selected for I2C4 clock" +#endif + +/** + * @brief LPTIM1 clock frequency. + */ +#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM1CLK STM32_PCLK1 + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI +#define STM32_LPTIM1CLK STM32_LSICLK + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16 +#define STM32_LPTIM1CLK STM32_HSI16CLK + +#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE +#define STM32_LPTIM1CLK STM32_LSECLK + +#else +#error "invalid source selected for LPTIM1 clock" +#endif + +/** + * @brief LPTIM2 clock frequency. + */ +#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM2CLK STM32_PCLK1 + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI +#define STM32_LPTIM2CLK STM32_LSICLK + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16 +#define STM32_LPTIM2CLK STM32_HSI16CLK + +#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE +#define STM32_LPTIM2CLK STM32_LSECLK + +#else +#error "invalid source selected for LPTIM2 clock" +#endif + +/** + * @brief LPTIM3 clock frequency. + */ +#if (STM32_LPTIM3SEL == STM32_LPTIM3SEL_PCLK1) || defined(__DOXYGEN__) +#define STM32_LPTIM3CLK STM32_PCLK1 + +#elif STM32_LPTIM3SEL == STM32_LPTIM3SEL_LSI +#define STM32_LPTIM3CLK STM32_LSICLK + +#elif STM32_LPTIM3SEL == STM32_LPTIM3SEL_HSI16 +#define STM32_LPTIM3CLK STM32_HSI16CLK + +#elif STM32_LPTIM3SEL == STM32_LPTIM3SEL_LSE +#define STM32_LPTIM3CLK STM32_LSECLK + +#else +#error "invalid source selected for LPTIM3 clock" +#endif + +/** + * @brief 48MHz clock frequency. + */ +#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__) +#define STM32_48CLK STM32_HSI48CLK + +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1 +#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE) + +#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL +#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) + +#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI +#define STM32_48CLK STM32_MSICLK + +#else +#error "invalid source selected for 48CLK clock" +#endif + +/** + * @brief SAI1 clock frequency. + */ +#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2 +#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL +#define STM32_SAI1CLK STM32_PLL_P_CLKOUT + +#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK +#define STM32_SAI1CLK 0 /* Unknown, would require a board value */ + +#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16 +#define STM32_SAI1CLK STM32_HSI16CLK + +#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF +#define STM32_SAI1CLK 0 + +#else +#error "invalid source selected for SAI1 clock" +#endif + +/** + * @brief SAI2 clock frequency. + */ +#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__) +#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT + +#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2 +#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT + +#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL +#define STM32_SAI2CLK STM32_PLL_P_CLKOUT + +#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK +#define STM32_SAI2CLK 0 /* Unknown, would require a board value */ + +#elif STM32_SAI2SEL == STM32_SAI2SEL_HSI16 +#define STM32_SAI2CLK STM32_HSI16CLK + +#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF +#define STM32_SAI2CLK 0 + +#else +#error "invalid source selected for SAI2 clock" +#endif + +/** + * @brief SDMMC clock frequency. + */ +#if (STM32_SDMMCSEL == STM32_SDMMCSEL_48CLK) || defined(__DOXYGEN__) +#define STM32_SDMMCCLK STM32_48CLK + +#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLLSAI3CLK +#define STM32_SDMMCCLK STM32_PLL_P_CLKOUT + +#else +#error "invalid source selected for SDMMC clock" +#endif + +/** + * @brief USB clock point. + */ +#define STM32_USBCLK STM32_48CLK + +/** + * @brief RNG clock point. + */ +#define STM32_RNGCLK STM32_48CLK + +/** + * @brief ADC clock frequency. + */ +#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__) +#define STM32_ADCCLK 0 + +#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1 +#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT + +#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK +#define STM32_ADCCLK STM32_SYSCLK + +#else +#error "invalid source selected for ADC clock" +#endif + +/** + * @brief DFSDM clock frequency. + */ +#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__) +#define STM32_DFSDMCLK STM32_PCLK2 + +#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK +#define STM32_DFSDMCLK STM32_SYSCLK + +#else +#error "invalid source selected for DFSDM clock" +#endif + +/** + * @brief SDMMC frequency. + */ +#define STM32_SDMMC1CLK STM32_48CLK + +/** + * @brief OSPI clock frequency. + */ +#if (STM32_OSPISEL == STM32_OSPISEL_SYSCLK) || defined(__DOXYGEN__) +#define STM32_OSPICLK STM32_SYSCLK + +#elif STM32_OSPISEL == STM32_OSPISEL_MSI +#define STM32_OSPICLK STM32_MSICLK + +#elif STM32_OSPISEL == STM32_OSPISEL_48CLK +#define STM32_OSPICLK STM32_PLLSAI1_Q_CLKOUT + +#else +#error "invalid source selected for OSPI clock" +#endif + +/** + * @brief Clock of timers connected to APB1 + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Clock of timers connected to APB2. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS + +#else +#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS +#endif + +/** + * @brief Flash settings for MSI. + */ +#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS + +#elif STM32_MSICLK <= STM32_1WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS + +#elif STM32_MSICLK <= STM32_2WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS + +#elif STM32_MSICLK <= STM32_3WS_THRESHOLD +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS + +#else +#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "mpu_v7m.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_exti.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L5xx/platform.mk b/os/hal/ports/STM32/STM32L5xx/platform.mk index d2bfad33f6..6687ddf596 100644 --- a/os/hal/ports/STM32/STM32L5xx/platform.mk +++ b/os/hal/ports/STM32/STM32L5xx/platform.mk @@ -1,34 +1,34 @@ -# Required platform files. -PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L5xx/stm32_isr.c \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L5xx/hal_lld.c - -# Required include directories. -PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/STM32/STM32L5xx - -# Optional platform files. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(HALCONFDIR),) - ifeq ($(CONFDIR),) - HALCONFDIR = . - else - HALCONFDIR := $(CONFDIR) - endif -endif - -HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) - -else -endif - -# Drivers compatible with the platform. -include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk - -# Shared variables -ALLCSRC += $(PLATFORMSRC) -ALLINC += $(PLATFORMINC) +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L5xx/stm32_isr.c \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L5xx/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/STM32/STM32L5xx + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +else +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/STM32/STM32L5xx/stm32_dmamux.h b/os/hal/ports/STM32/STM32L5xx/stm32_dmamux.h index 89862d5ac8..d2a2e35529 100644 --- a/os/hal/ports/STM32/STM32L5xx/stm32_dmamux.h +++ b/os/hal/ports/STM32/STM32L5xx/stm32_dmamux.h @@ -1,162 +1,162 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L5xx/stm32_dmamux.h - * @brief STM32L5xx DMAMUX handler header. - * - * @addtogroup STM32L5xx_DMAMUX - * @{ - */ - -#ifndef STM32_DMAMUX_H -#define STM32_DMAMUX_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name DMAMUX1 request sources - * @{ - */ -#define STM32_DMAMUX1_REQ_GEN0 1 -#define STM32_DMAMUX1_REQ_GEN1 2 -#define STM32_DMAMUX1_REQ_GEN2 3 -#define STM32_DMAMUX1_REQ_GEN3 4 -#define STM32_DMAMUX1_ADC1 5 -#define STM32_DMAMUX1_ADC2 7 -#define STM32_DMAMUX1_DAC1_CH1 7 -#define STM32_DMAMUX1_DAC1_CH2 8 -#define STM32_DMAMUX1_TIM6_UP 9 -#define STM32_DMAMUX1_TIM7_UP 10 -#define STM32_DMAMUX1_SPI1_RX 11 -#define STM32_DMAMUX1_SPI1_TX 12 -#define STM32_DMAMUX1_SPI2_RX 13 -#define STM32_DMAMUX1_SPI2_TX 14 -#define STM32_DMAMUX1_SPI3_RX 15 -#define STM32_DMAMUX1_SPI3_TX 16 -#define STM32_DMAMUX1_I2C1_RX 17 -#define STM32_DMAMUX1_I2C1_TX 18 -#define STM32_DMAMUX1_I2C2_RX 19 -#define STM32_DMAMUX1_I2C2_TX 20 -#define STM32_DMAMUX1_I2C3_RX 21 -#define STM32_DMAMUX1_I2C3_TX 22 -#define STM32_DMAMUX1_I2C4_RX 23 -#define STM32_DMAMUX1_I2C4_TX 24 -#define STM32_DMAMUX1_USART1_RX 25 -#define STM32_DMAMUX1_USART1_TX 26 -#define STM32_DMAMUX1_USART2_RX 27 -#define STM32_DMAMUX1_USART2_TX 28 -#define STM32_DMAMUX1_USART3_RX 29 -#define STM32_DMAMUX1_USART3_TX 30 -#define STM32_DMAMUX1_UART4_RX 31 -#define STM32_DMAMUX1_UART4_TX 32 -#define STM32_DMAMUX1_UART5_RX 33 -#define STM32_DMAMUX1_UART5_TX 34 -#define STM32_DMAMUX1_LPUART1_RX 35 -#define STM32_DMAMUX1_LPUART1_TX 36 -#define STM32_DMAMUX1_SAI1_A 37 -#define STM32_DMAMUX1_SAI1_B 38 -#define STM32_DMAMUX1_SAI2_A 39 -#define STM32_DMAMUX1_SAI2_B 20 -#define STM32_DMAMUX1_OCTOSPI1 41 -#define STM32_DMAMUX1_TIM1_CH1 42 -#define STM32_DMAMUX1_TIM1_CH2 43 -#define STM32_DMAMUX1_TIM1_CH3 44 -#define STM32_DMAMUX1_TIM1_CH4 45 -#define STM32_DMAMUX1_TIM1_UP 46 -#define STM32_DMAMUX1_TIM1_TRIG 47 -#define STM32_DMAMUX1_TIM1_COM 48 -#define STM32_DMAMUX1_TIM8_CH1 49 -#define STM32_DMAMUX1_TIM8_CH2 50 -#define STM32_DMAMUX1_TIM8_CH3 51 -#define STM32_DMAMUX1_TIM8_CH4 52 -#define STM32_DMAMUX1_TIM8_UP 53 -#define STM32_DMAMUX1_TIM8_TRIG 54 -#define STM32_DMAMUX1_TIM8_COM 55 -#define STM32_DMAMUX1_TIM2_CH1 56 -#define STM32_DMAMUX1_TIM2_CH2 57 -#define STM32_DMAMUX1_TIM2_CH3 58 -#define STM32_DMAMUX1_TIM2_CH4 59 -#define STM32_DMAMUX1_TIM2_UP 60 -#define STM32_DMAMUX1_TIM3_CH1 61 -#define STM32_DMAMUX1_TIM3_CH2 62 -#define STM32_DMAMUX1_TIM3_CH3 63 -#define STM32_DMAMUX1_TIM3_CH4 64 -#define STM32_DMAMUX1_TIM3_UP 65 -#define STM32_DMAMUX1_TIM3_TRIG 66 -#define STM32_DMAMUX1_TIM4_CH1 67 -#define STM32_DMAMUX1_TIM4_CH2 68 -#define STM32_DMAMUX1_TIM4_CH3 69 -#define STM32_DMAMUX1_TIM4_CH4 70 -#define STM32_DMAMUX1_TIM4_UP 71 -#define STM32_DMAMUX1_TIM5_CH1 72 -#define STM32_DMAMUX1_TIM5_CH2 73 -#define STM32_DMAMUX1_TIM5_CH3 74 -#define STM32_DMAMUX1_TIM5_CH4 75 -#define STM32_DMAMUX1_TIM5_UP 76 -#define STM32_DMAMUX1_TIM5_TRIG 77 -#define STM32_DMAMUX1_TIM15_CH1 78 -#define STM32_DMAMUX1_TIM15_UP 79 -#define STM32_DMAMUX1_TIM15_TRIG 80 -#define STM32_DMAMUX1_TIM15_COM 81 -#define STM32_DMAMUX1_TIM16_CH1 82 -#define STM32_DMAMUX1_TIM16_UP 83 -#define STM32_DMAMUX1_TIM17_CH1 84 -#define STM32_DMAMUX1_TIM17_UP 85 -#define STM32_DMAMUX1_DFSDM1_FLT0 86 -#define STM32_DMAMUX1_DFSDM1_FLT1 87 -#define STM32_DMAMUX1_DFSDM1_FLT2 88 -#define STM32_DMAMUX1_DFSDM1_FLT3 89 -#define STM32_DMAMUX1_AES_IN 90 -#define STM32_DMAMUX1_AES_OUT 91 -#define STM32_DMAMUX1_HASH_IN 92 -#define STM32_DMAMUX1_USBPD_TX 93 -#define STM32_DMAMUX1_USBPD_RX 94 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* STM32_DMAMUX_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L5xx/stm32_dmamux.h + * @brief STM32L5xx DMAMUX handler header. + * + * @addtogroup STM32L5xx_DMAMUX + * @{ + */ + +#ifndef STM32_DMAMUX_H +#define STM32_DMAMUX_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name DMAMUX1 request sources + * @{ + */ +#define STM32_DMAMUX1_REQ_GEN0 1 +#define STM32_DMAMUX1_REQ_GEN1 2 +#define STM32_DMAMUX1_REQ_GEN2 3 +#define STM32_DMAMUX1_REQ_GEN3 4 +#define STM32_DMAMUX1_ADC1 5 +#define STM32_DMAMUX1_ADC2 7 +#define STM32_DMAMUX1_DAC1_CH1 7 +#define STM32_DMAMUX1_DAC1_CH2 8 +#define STM32_DMAMUX1_TIM6_UP 9 +#define STM32_DMAMUX1_TIM7_UP 10 +#define STM32_DMAMUX1_SPI1_RX 11 +#define STM32_DMAMUX1_SPI1_TX 12 +#define STM32_DMAMUX1_SPI2_RX 13 +#define STM32_DMAMUX1_SPI2_TX 14 +#define STM32_DMAMUX1_SPI3_RX 15 +#define STM32_DMAMUX1_SPI3_TX 16 +#define STM32_DMAMUX1_I2C1_RX 17 +#define STM32_DMAMUX1_I2C1_TX 18 +#define STM32_DMAMUX1_I2C2_RX 19 +#define STM32_DMAMUX1_I2C2_TX 20 +#define STM32_DMAMUX1_I2C3_RX 21 +#define STM32_DMAMUX1_I2C3_TX 22 +#define STM32_DMAMUX1_I2C4_RX 23 +#define STM32_DMAMUX1_I2C4_TX 24 +#define STM32_DMAMUX1_USART1_RX 25 +#define STM32_DMAMUX1_USART1_TX 26 +#define STM32_DMAMUX1_USART2_RX 27 +#define STM32_DMAMUX1_USART2_TX 28 +#define STM32_DMAMUX1_USART3_RX 29 +#define STM32_DMAMUX1_USART3_TX 30 +#define STM32_DMAMUX1_UART4_RX 31 +#define STM32_DMAMUX1_UART4_TX 32 +#define STM32_DMAMUX1_UART5_RX 33 +#define STM32_DMAMUX1_UART5_TX 34 +#define STM32_DMAMUX1_LPUART1_RX 35 +#define STM32_DMAMUX1_LPUART1_TX 36 +#define STM32_DMAMUX1_SAI1_A 37 +#define STM32_DMAMUX1_SAI1_B 38 +#define STM32_DMAMUX1_SAI2_A 39 +#define STM32_DMAMUX1_SAI2_B 20 +#define STM32_DMAMUX1_OCTOSPI1 41 +#define STM32_DMAMUX1_TIM1_CH1 42 +#define STM32_DMAMUX1_TIM1_CH2 43 +#define STM32_DMAMUX1_TIM1_CH3 44 +#define STM32_DMAMUX1_TIM1_CH4 45 +#define STM32_DMAMUX1_TIM1_UP 46 +#define STM32_DMAMUX1_TIM1_TRIG 47 +#define STM32_DMAMUX1_TIM1_COM 48 +#define STM32_DMAMUX1_TIM8_CH1 49 +#define STM32_DMAMUX1_TIM8_CH2 50 +#define STM32_DMAMUX1_TIM8_CH3 51 +#define STM32_DMAMUX1_TIM8_CH4 52 +#define STM32_DMAMUX1_TIM8_UP 53 +#define STM32_DMAMUX1_TIM8_TRIG 54 +#define STM32_DMAMUX1_TIM8_COM 55 +#define STM32_DMAMUX1_TIM2_CH1 56 +#define STM32_DMAMUX1_TIM2_CH2 57 +#define STM32_DMAMUX1_TIM2_CH3 58 +#define STM32_DMAMUX1_TIM2_CH4 59 +#define STM32_DMAMUX1_TIM2_UP 60 +#define STM32_DMAMUX1_TIM3_CH1 61 +#define STM32_DMAMUX1_TIM3_CH2 62 +#define STM32_DMAMUX1_TIM3_CH3 63 +#define STM32_DMAMUX1_TIM3_CH4 64 +#define STM32_DMAMUX1_TIM3_UP 65 +#define STM32_DMAMUX1_TIM3_TRIG 66 +#define STM32_DMAMUX1_TIM4_CH1 67 +#define STM32_DMAMUX1_TIM4_CH2 68 +#define STM32_DMAMUX1_TIM4_CH3 69 +#define STM32_DMAMUX1_TIM4_CH4 70 +#define STM32_DMAMUX1_TIM4_UP 71 +#define STM32_DMAMUX1_TIM5_CH1 72 +#define STM32_DMAMUX1_TIM5_CH2 73 +#define STM32_DMAMUX1_TIM5_CH3 74 +#define STM32_DMAMUX1_TIM5_CH4 75 +#define STM32_DMAMUX1_TIM5_UP 76 +#define STM32_DMAMUX1_TIM5_TRIG 77 +#define STM32_DMAMUX1_TIM15_CH1 78 +#define STM32_DMAMUX1_TIM15_UP 79 +#define STM32_DMAMUX1_TIM15_TRIG 80 +#define STM32_DMAMUX1_TIM15_COM 81 +#define STM32_DMAMUX1_TIM16_CH1 82 +#define STM32_DMAMUX1_TIM16_UP 83 +#define STM32_DMAMUX1_TIM17_CH1 84 +#define STM32_DMAMUX1_TIM17_UP 85 +#define STM32_DMAMUX1_DFSDM1_FLT0 86 +#define STM32_DMAMUX1_DFSDM1_FLT1 87 +#define STM32_DMAMUX1_DFSDM1_FLT2 88 +#define STM32_DMAMUX1_DFSDM1_FLT3 89 +#define STM32_DMAMUX1_AES_IN 90 +#define STM32_DMAMUX1_AES_OUT 91 +#define STM32_DMAMUX1_HASH_IN 92 +#define STM32_DMAMUX1_USBPD_TX 93 +#define STM32_DMAMUX1_USBPD_RX 94 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_DMAMUX_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L5xx/stm32_isr.c b/os/hal/ports/STM32/STM32L5xx/stm32_isr.c index afc6948097..dc5e5ba069 100644 --- a/os/hal/ports/STM32/STM32L5xx/stm32_isr.c +++ b/os/hal/ports/STM32/STM32L5xx/stm32_isr.c @@ -1,192 +1,192 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L5xx/stm32_isr.c - * @brief STM32L5xx ISR handler code. - * - * @addtogroup STM32L5xx_ISR - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#define exti_serve_irq(pr, channel) { \ - \ - if ((pr) & (1U << (channel))) { \ - _pal_isr_code(channel); \ - } \ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#include "stm32_exti0.inc" -#include "stm32_exti1.inc" -#include "stm32_exti2.inc" -#include "stm32_exti3.inc" -#include "stm32_exti4.inc" -#include "stm32_exti5.inc" -#include "stm32_exti6.inc" -#include "stm32_exti7.inc" -#include "stm32_exti8.inc" -#include "stm32_exti9.inc" -#include "stm32_exti10.inc" -#include "stm32_exti11.inc" -#include "stm32_exti12.inc" -#include "stm32_exti13.inc" -#include "stm32_exti14.inc" -#include "stm32_exti15.inc" -#include "stm32_exti16-35_38.inc" -#include "stm32_exti17.inc" -#include "stm32_exti18.inc" -#include "stm32_exti19.inc" -#include "stm32_exti20.inc" -#include "stm32_exti21_22.inc" - -#include "stm32_usart1.inc" -#include "stm32_usart2.inc" -#include "stm32_usart3.inc" -#include "stm32_uart4.inc" -#include "stm32_uart5.inc" -#include "stm32_lpuart1.inc" - -#include "stm32_tim1.inc" -#include "stm32_tim2.inc" -#include "stm32_tim3.inc" -#include "stm32_tim4.inc" -#include "stm32_tim5.inc" -#include "stm32_tim6.inc" -#include "stm32_tim7.inc" -#include "stm32_tim8.inc" -#include "stm32_tim15.inc" -#include "stm32_tim16.inc" -#include "stm32_tim17.inc" - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables IRQ sources. - * - * @notapi - */ -void irqInit(void) { - - exti0_irq_init(); - exti1_irq_init(); - exti2_irq_init(); - exti3_irq_init(); - exti4_irq_init(); - exti5_irq_init(); - exti6_irq_init(); - exti7_irq_init(); - exti8_irq_init(); - exti9_irq_init(); - exti10_irq_init(); - exti11_irq_init(); - exti12_irq_init(); - exti13_irq_init(); - exti14_irq_init(); - exti15_irq_init(); - exti16_exti35_38_irq_init(); - exti17_irq_init(); - exti18_irq_init(); - exti19_irq_init(); - exti21_22_irq_init(); - - tim1_tim15_tim16_tim17_irq_init(); - tim2_irq_init(); - tim3_irq_init(); - tim4_irq_init(); - tim5_irq_init(); - tim6_irq_init(); - tim7_irq_init(); - tim8_irq_init(); - - usart1_irq_init(); - usart2_irq_init(); - usart3_irq_init(); - uart4_irq_init(); - uart5_irq_init(); - lpuart1_irq_init(); -} - -/** - * @brief Disables IRQ sources. - * - * @notapi - */ -void irqDeinit(void) { - - exti0_irq_deinit(); - exti1_irq_deinit(); - exti2_irq_deinit(); - exti3_irq_deinit(); - exti4_irq_deinit(); - exti5_irq_deinit(); - exti6_irq_deinit(); - exti7_irq_deinit(); - exti8_irq_deinit(); - exti9_irq_deinit(); - exti10_irq_deinit(); - exti11_irq_deinit(); - exti12_irq_deinit(); - exti13_irq_deinit(); - exti14_irq_deinit(); - exti15_irq_deinit(); - exti16_exti35_38_irq_deinit(); - exti17_irq_deinit(); - exti18_irq_deinit(); - exti19_irq_deinit(); - exti21_22_irq_deinit(); - - tim1_tim15_tim16_tim17_irq_deinit(); - tim2_irq_deinit(); - tim3_irq_deinit(); - tim4_irq_deinit(); - tim5_irq_deinit(); - tim6_irq_deinit(); - tim7_irq_deinit(); - tim8_irq_deinit(); - - usart1_irq_deinit(); - usart2_irq_deinit(); - usart3_irq_deinit(); - uart4_irq_deinit(); - uart5_irq_deinit(); - lpuart1_irq_deinit(); -} - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L5xx/stm32_isr.c + * @brief STM32L5xx ISR handler code. + * + * @addtogroup STM32L5xx_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#define exti_serve_irq(pr, channel) { \ + \ + if ((pr) & (1U << (channel))) { \ + _pal_isr_code(channel); \ + } \ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "stm32_exti0.inc" +#include "stm32_exti1.inc" +#include "stm32_exti2.inc" +#include "stm32_exti3.inc" +#include "stm32_exti4.inc" +#include "stm32_exti5.inc" +#include "stm32_exti6.inc" +#include "stm32_exti7.inc" +#include "stm32_exti8.inc" +#include "stm32_exti9.inc" +#include "stm32_exti10.inc" +#include "stm32_exti11.inc" +#include "stm32_exti12.inc" +#include "stm32_exti13.inc" +#include "stm32_exti14.inc" +#include "stm32_exti15.inc" +#include "stm32_exti16-35_38.inc" +#include "stm32_exti17.inc" +#include "stm32_exti18.inc" +#include "stm32_exti19.inc" +#include "stm32_exti20.inc" +#include "stm32_exti21_22.inc" + +#include "stm32_usart1.inc" +#include "stm32_usart2.inc" +#include "stm32_usart3.inc" +#include "stm32_uart4.inc" +#include "stm32_uart5.inc" +#include "stm32_lpuart1.inc" + +#include "stm32_tim1.inc" +#include "stm32_tim2.inc" +#include "stm32_tim3.inc" +#include "stm32_tim4.inc" +#include "stm32_tim5.inc" +#include "stm32_tim6.inc" +#include "stm32_tim7.inc" +#include "stm32_tim8.inc" +#include "stm32_tim15.inc" +#include "stm32_tim16.inc" +#include "stm32_tim17.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables IRQ sources. + * + * @notapi + */ +void irqInit(void) { + + exti0_irq_init(); + exti1_irq_init(); + exti2_irq_init(); + exti3_irq_init(); + exti4_irq_init(); + exti5_irq_init(); + exti6_irq_init(); + exti7_irq_init(); + exti8_irq_init(); + exti9_irq_init(); + exti10_irq_init(); + exti11_irq_init(); + exti12_irq_init(); + exti13_irq_init(); + exti14_irq_init(); + exti15_irq_init(); + exti16_exti35_38_irq_init(); + exti17_irq_init(); + exti18_irq_init(); + exti19_irq_init(); + exti21_22_irq_init(); + + tim1_tim15_tim16_tim17_irq_init(); + tim2_irq_init(); + tim3_irq_init(); + tim4_irq_init(); + tim5_irq_init(); + tim6_irq_init(); + tim7_irq_init(); + tim8_irq_init(); + + usart1_irq_init(); + usart2_irq_init(); + usart3_irq_init(); + uart4_irq_init(); + uart5_irq_init(); + lpuart1_irq_init(); +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + + exti0_irq_deinit(); + exti1_irq_deinit(); + exti2_irq_deinit(); + exti3_irq_deinit(); + exti4_irq_deinit(); + exti5_irq_deinit(); + exti6_irq_deinit(); + exti7_irq_deinit(); + exti8_irq_deinit(); + exti9_irq_deinit(); + exti10_irq_deinit(); + exti11_irq_deinit(); + exti12_irq_deinit(); + exti13_irq_deinit(); + exti14_irq_deinit(); + exti15_irq_deinit(); + exti16_exti35_38_irq_deinit(); + exti17_irq_deinit(); + exti18_irq_deinit(); + exti19_irq_deinit(); + exti21_22_irq_deinit(); + + tim1_tim15_tim16_tim17_irq_deinit(); + tim2_irq_deinit(); + tim3_irq_deinit(); + tim4_irq_deinit(); + tim5_irq_deinit(); + tim6_irq_deinit(); + tim7_irq_deinit(); + tim8_irq_deinit(); + + usart1_irq_deinit(); + usart2_irq_deinit(); + usart3_irq_deinit(); + uart4_irq_deinit(); + uart5_irq_deinit(); + lpuart1_irq_deinit(); +} + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L5xx/stm32_isr.h b/os/hal/ports/STM32/STM32L5xx/stm32_isr.h index 48b4a1da4e..62a7f11625 100644 --- a/os/hal/ports/STM32/STM32L5xx/stm32_isr.h +++ b/os/hal/ports/STM32/STM32L5xx/stm32_isr.h @@ -1,299 +1,299 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L5xx/stm32_isr.h - * @brief STM32L5xx ISR handler header. - * - * @addtogroup STM32L5xx_ISR - * @{ - */ - -#ifndef STM32_ISR_H -#define STM32_ISR_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISRs suppressed in standard drivers - * @{ - */ -#define STM32_TIM1_SUPPRESS_ISR -#define STM32_TIM2_SUPPRESS_ISR -#define STM32_TIM3_SUPPRESS_ISR -#define STM32_TIM4_SUPPRESS_ISR -#define STM32_TIM5_SUPPRESS_ISR -#define STM32_TIM6_SUPPRESS_ISR -#define STM32_TIM7_SUPPRESS_ISR -#define STM32_TIM8_SUPPRESS_ISR -#define STM32_TIM15_SUPPRESS_ISR -#define STM32_TIM16_SUPPRESS_ISR -#define STM32_TIM17_SUPPRESS_ISR - -#define STM32_USART1_SUPPRESS_ISR -#define STM32_USART2_SUPPRESS_ISR -#define STM32_USART3_SUPPRESS_ISR -#define STM32_UART4_SUPPRESS_ISR -#define STM32_UART5_SUPPRESS_ISR -#define STM32_LPUART1_SUPPRESS_ISR -/** @} */ - -/** - * @name ISR names and numbers - * @{ - */ -/* - * ADC unit. - */ -#define STM32_ADC12_HANDLER VectorD4 - -#define STM32_ADC12_NUMBER 37 - -/* - * FDCAN unit. - */ -#define STM32_FDCAN1_IT0_HANDLER VectorDC -#define STM32_FDCAN1_IT1_HANDLER VectorE0 - -#define STM32_FDCAN1_IT0_NUMBER 39 -#define STM32_FDCAN1_IT1_NUMBER 40 - -/* - * DMA unit. - */ -#define STM32_DMA1_CH1_HANDLER VectorB4 -#define STM32_DMA1_CH2_HANDLER VectorB8 -#define STM32_DMA1_CH3_HANDLER VectorBC -#define STM32_DMA1_CH4_HANDLER VectorC0 -#define STM32_DMA1_CH5_HANDLER VectorC4 -#define STM32_DMA1_CH6_HANDLER VectorC8 -#define STM32_DMA1_CH7_HANDLER VectorCC -#define STM32_DMA1_CH8_HANDLER VectorD0 -#define STM32_DMA2_CH1_HANDLER Vector180 -#define STM32_DMA2_CH2_HANDLER Vector184 -#define STM32_DMA2_CH3_HANDLER Vector188 -#define STM32_DMA2_CH4_HANDLER Vector18C -#define STM32_DMA2_CH5_HANDLER Vector190 -#define STM32_DMA2_CH6_HANDLER Vector194 -#define STM32_DMA2_CH7_HANDLER Vector198 -#define STM32_DMA2_CH8_HANDLER Vector19C - -#define STM32_DMA1_CH1_NUMBER 29 -#define STM32_DMA1_CH2_NUMBER 30 -#define STM32_DMA1_CH3_NUMBER 31 -#define STM32_DMA1_CH4_NUMBER 32 -#define STM32_DMA1_CH5_NUMBER 33 -#define STM32_DMA1_CH6_NUMBER 34 -#define STM32_DMA1_CH7_NUMBER 35 -#define STM32_DMA1_CH8_NUMBER 36 -#define STM32_DMA2_CH1_NUMBER 80 -#define STM32_DMA2_CH2_NUMBER 81 -#define STM32_DMA2_CH3_NUMBER 82 -#define STM32_DMA2_CH4_NUMBER 83 -#define STM32_DMA2_CH5_NUMBER 84 -#define STM32_DMA2_CH6_NUMBER 85 -#define STM32_DMA2_CH7_NUMBER 86 -#define STM32_DMA2_CH8_NUMBER 87 - -/* - * EXTI unit. - */ -#define STM32_EXTI0_HANDLER Vector58 -#define STM32_EXTI1_HANDLER Vector5C -#define STM32_EXTI2_HANDLER Vector60 -#define STM32_EXTI3_HANDLER Vector64 -#define STM32_EXTI4_HANDLER Vector68 -#define STM32_EXTI5_HANDLER Vector9C -#define STM32_EXTI6_HANDLER Vector9C -#define STM32_EXTI7_HANDLER Vector9C -#define STM32_EXTI8_HANDLER Vector9C -#define STM32_EXTI9_HANDLER Vector9C -#define STM32_EXTI10_HANDLER VectorE0 -#define STM32_EXTI11_HANDLER VectorE0 -#define STM32_EXTI12_HANDLER VectorE0 -#define STM32_EXTI13_HANDLER VectorE0 -#define STM32_EXTI14_HANDLER VectorE0 -#define STM32_EXTI15_HANDLER VectorE0 -#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1..PVM4 */ -#define STM32_EXTI17_HANDLER Vector48 /* RTC */ -#define STM32_EXTI18_HANDLER Vector4C /* RTC (secure) */ -#define STM32_EXTI19_HANDLER Vector50 /* TAMP */ -#define STM32_EXTI20_HANDLER Vector54 /* TAMP (secure) */ -#define STM32_EXTI21_22_HANDLER Vector160 /* COMP1..2 */ - -#define STM32_EXTI0_NUMBER 11 -#define STM32_EXTI1_NUMBER 12 -#define STM32_EXTI2_NUMBER 13 -#define STM32_EXTI3_NUMBER 14 -#define STM32_EXTI4_NUMBER 15 -#define STM32_EXTI5_NUMBER 16 -#define STM32_EXTI6_NUMBER 17 -#define STM32_EXTI7_NUMBER 18 -#define STM32_EXTI8_NUMBER 19 -#define STM32_EXTI9_NUMBER 20 -#define STM32_EXTI10_NUMBER 21 -#define STM32_EXTI11_NUMBER 22 -#define STM32_EXTI12_NUMBER 23 -#define STM32_EXTI13_NUMBER 24 -#define STM32_EXTI14_NUMBER 25 -#define STM32_EXTI15_NUMBER 26 -#define STM32_EXTI1635_38_NUMBER 1 -#define STM32_EXTI17_NUMBER 2 -#define STM32_EXTI18_NUMBER 3 -#define STM32_EXTI19_NUMBER 4 -#define STM32_EXTI20_NUMBER 5 -#define STM32_EXTI21_22_NUMBER 72 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER Vector11C -#define STM32_I2C1_ERROR_HANDLER Vector120 -#define STM32_I2C2_EVENT_HANDLER Vector124 -#define STM32_I2C2_ERROR_HANDLER Vector138 -#define STM32_I2C3_EVENT_HANDLER Vector188 -#define STM32_I2C3_ERROR_HANDLER Vector18C -#define STM32_I2C4_EVENT_HANDLER Vector1B8 -#define STM32_I2C4_ERROR_HANDLER Vector1BC - -#define STM32_I2C1_EVENT_NUMBER 55 -#define STM32_I2C1_ERROR_NUMBER 56 -#define STM32_I2C2_EVENT_NUMBER 57 -#define STM32_I2C2_ERROR_NUMBER 58 -#define STM32_I2C3_EVENT_NUMBER 88 -#define STM32_I2C3_ERROR_NUMBER 89 -#define STM32_I2C4_EVENT_NUMBER 100 -#define STM32_I2C4_ERROR_NUMBER 101 - -/* - * OCTOSPI unit. - */ -#define STM32_OCTOSPI1_HANDLER Vector170 - -#define STM32_OCTOSPI1_NUMBER 76 - -/* - * SDMMC unit. - */ -#define STM32_SDMMC1_HANDLER Vector178 - -#define STM32_SDMMC1_NUMBER 78 - -/* - * TIM units. - */ -#define STM32_TIM1_BRK_HANDLER VectorE4 -#define STM32_TIM1_UP_HANDLER VectorE8 -#define STM32_TIM1_TRGCO_HANDLER VectorEC -#define STM32_TIM1_CC_HANDLER VectorF0 -#define STM32_TIM2_HANDLER VectorF4 -#define STM32_TIM3_HANDLER VectorF8 -#define STM32_TIM4_HANDLER VectorFC -#define STM32_TIM5_HANDLER Vector100 -#define STM32_TIM6_HANDLER Vector104 -#define STM32_TIM7_HANDLER Vector108 -#define STM32_TIM8_BRK_HANDLER Vector10C -#define STM32_TIM8_UP_HANDLER Vector110 -#define STM32_TIM8_TRGCO_HANDLER Vector114 -#define STM32_TIM8_CC_HANDLER Vector118 -#define STM32_TIM15_HANDLER Vector154 -#define STM32_TIM16_HANDLER Vector158 -#define STM32_TIM17_HANDLER Vector15C - -#define STM32_TIM1_BRK_NUMBER 41 -#define STM32_TIM1_UP_NUMBER 42 -#define STM32_TIM1_TRGCO_NUMBER 43 -#define STM32_TIM1_CC_NUMBER 44 -#define STM32_TIM2_NUMBER 45 -#define STM32_TIM3_NUMBER 46 -#define STM32_TIM4_NUMBER 47 -#define STM32_TIM5_NUMBER 48 -#define STM32_TIM6_NUMBER 49 -#define STM32_TIM7_NUMBER 50 -#define STM32_TIM8_BRK_NUMBER 51 -#define STM32_TIM8_UP_NUMBER 52 -#define STM32_TIM8_TRGCO_NUMBER 53 -#define STM32_TIM8_CC_NUMBER 54 -#define STM32_TIM15_NUMBER 69 -#define STM32_TIM16_NUMBER 70 -#define STM32_TIM17_NUMBER 71 - -/* - * USART/UART units. - */ -#define STM32_USART1_HANDLER Vector134 -#define STM32_USART2_HANDLER Vector138 -#define STM32_USART3_HANDLER Vector13C -#define STM32_UART4_HANDLER Vector140 -#define STM32_UART5_HANDLER Vector144 -#define STM32_LPUART1_HANDLER Vector148 - -#define STM32_USART1_NUMBER 61 -#define STM32_USART2_NUMBER 62 -#define STM32_USART3_NUMBER 63 -#define STM32_UART4_NUMBER 64 -#define STM32_UART5_NUMBER 65 -#define STM32_LPUART1_NUMBER 66 - -/* - * USB/OTG units. - */ -#define STM32_USB_FS_HANDLER Vector164 - -#define STM32_USB_FS_NUMBER 73 - -/* - * FSMC unit. - */ -#define STM32_FSMC_HANDLER Vector16C - -#define STM32_FSMC_NUMBER 75 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void irqInit(void); - void irqDeinit(void); -#ifdef __cplusplus -} -#endif - -#endif /* STM32_ISR_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L5xx/stm32_isr.h + * @brief STM32L5xx ISR handler header. + * + * @addtogroup STM32L5xx_ISR + * @{ + */ + +#ifndef STM32_ISR_H +#define STM32_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISRs suppressed in standard drivers + * @{ + */ +#define STM32_TIM1_SUPPRESS_ISR +#define STM32_TIM2_SUPPRESS_ISR +#define STM32_TIM3_SUPPRESS_ISR +#define STM32_TIM4_SUPPRESS_ISR +#define STM32_TIM5_SUPPRESS_ISR +#define STM32_TIM6_SUPPRESS_ISR +#define STM32_TIM7_SUPPRESS_ISR +#define STM32_TIM8_SUPPRESS_ISR +#define STM32_TIM15_SUPPRESS_ISR +#define STM32_TIM16_SUPPRESS_ISR +#define STM32_TIM17_SUPPRESS_ISR + +#define STM32_USART1_SUPPRESS_ISR +#define STM32_USART2_SUPPRESS_ISR +#define STM32_USART3_SUPPRESS_ISR +#define STM32_UART4_SUPPRESS_ISR +#define STM32_UART5_SUPPRESS_ISR +#define STM32_LPUART1_SUPPRESS_ISR +/** @} */ + +/** + * @name ISR names and numbers + * @{ + */ +/* + * ADC unit. + */ +#define STM32_ADC12_HANDLER VectorD4 + +#define STM32_ADC12_NUMBER 37 + +/* + * FDCAN unit. + */ +#define STM32_FDCAN1_IT0_HANDLER VectorDC +#define STM32_FDCAN1_IT1_HANDLER VectorE0 + +#define STM32_FDCAN1_IT0_NUMBER 39 +#define STM32_FDCAN1_IT1_NUMBER 40 + +/* + * DMA unit. + */ +#define STM32_DMA1_CH1_HANDLER VectorB4 +#define STM32_DMA1_CH2_HANDLER VectorB8 +#define STM32_DMA1_CH3_HANDLER VectorBC +#define STM32_DMA1_CH4_HANDLER VectorC0 +#define STM32_DMA1_CH5_HANDLER VectorC4 +#define STM32_DMA1_CH6_HANDLER VectorC8 +#define STM32_DMA1_CH7_HANDLER VectorCC +#define STM32_DMA1_CH8_HANDLER VectorD0 +#define STM32_DMA2_CH1_HANDLER Vector180 +#define STM32_DMA2_CH2_HANDLER Vector184 +#define STM32_DMA2_CH3_HANDLER Vector188 +#define STM32_DMA2_CH4_HANDLER Vector18C +#define STM32_DMA2_CH5_HANDLER Vector190 +#define STM32_DMA2_CH6_HANDLER Vector194 +#define STM32_DMA2_CH7_HANDLER Vector198 +#define STM32_DMA2_CH8_HANDLER Vector19C + +#define STM32_DMA1_CH1_NUMBER 29 +#define STM32_DMA1_CH2_NUMBER 30 +#define STM32_DMA1_CH3_NUMBER 31 +#define STM32_DMA1_CH4_NUMBER 32 +#define STM32_DMA1_CH5_NUMBER 33 +#define STM32_DMA1_CH6_NUMBER 34 +#define STM32_DMA1_CH7_NUMBER 35 +#define STM32_DMA1_CH8_NUMBER 36 +#define STM32_DMA2_CH1_NUMBER 80 +#define STM32_DMA2_CH2_NUMBER 81 +#define STM32_DMA2_CH3_NUMBER 82 +#define STM32_DMA2_CH4_NUMBER 83 +#define STM32_DMA2_CH5_NUMBER 84 +#define STM32_DMA2_CH6_NUMBER 85 +#define STM32_DMA2_CH7_NUMBER 86 +#define STM32_DMA2_CH8_NUMBER 87 + +/* + * EXTI unit. + */ +#define STM32_EXTI0_HANDLER Vector58 +#define STM32_EXTI1_HANDLER Vector5C +#define STM32_EXTI2_HANDLER Vector60 +#define STM32_EXTI3_HANDLER Vector64 +#define STM32_EXTI4_HANDLER Vector68 +#define STM32_EXTI5_HANDLER Vector9C +#define STM32_EXTI6_HANDLER Vector9C +#define STM32_EXTI7_HANDLER Vector9C +#define STM32_EXTI8_HANDLER Vector9C +#define STM32_EXTI9_HANDLER Vector9C +#define STM32_EXTI10_HANDLER VectorE0 +#define STM32_EXTI11_HANDLER VectorE0 +#define STM32_EXTI12_HANDLER VectorE0 +#define STM32_EXTI13_HANDLER VectorE0 +#define STM32_EXTI14_HANDLER VectorE0 +#define STM32_EXTI15_HANDLER VectorE0 +#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1..PVM4 */ +#define STM32_EXTI17_HANDLER Vector48 /* RTC */ +#define STM32_EXTI18_HANDLER Vector4C /* RTC (secure) */ +#define STM32_EXTI19_HANDLER Vector50 /* TAMP */ +#define STM32_EXTI20_HANDLER Vector54 /* TAMP (secure) */ +#define STM32_EXTI21_22_HANDLER Vector160 /* COMP1..2 */ + +#define STM32_EXTI0_NUMBER 11 +#define STM32_EXTI1_NUMBER 12 +#define STM32_EXTI2_NUMBER 13 +#define STM32_EXTI3_NUMBER 14 +#define STM32_EXTI4_NUMBER 15 +#define STM32_EXTI5_NUMBER 16 +#define STM32_EXTI6_NUMBER 17 +#define STM32_EXTI7_NUMBER 18 +#define STM32_EXTI8_NUMBER 19 +#define STM32_EXTI9_NUMBER 20 +#define STM32_EXTI10_NUMBER 21 +#define STM32_EXTI11_NUMBER 22 +#define STM32_EXTI12_NUMBER 23 +#define STM32_EXTI13_NUMBER 24 +#define STM32_EXTI14_NUMBER 25 +#define STM32_EXTI15_NUMBER 26 +#define STM32_EXTI1635_38_NUMBER 1 +#define STM32_EXTI17_NUMBER 2 +#define STM32_EXTI18_NUMBER 3 +#define STM32_EXTI19_NUMBER 4 +#define STM32_EXTI20_NUMBER 5 +#define STM32_EXTI21_22_NUMBER 72 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER Vector11C +#define STM32_I2C1_ERROR_HANDLER Vector120 +#define STM32_I2C2_EVENT_HANDLER Vector124 +#define STM32_I2C2_ERROR_HANDLER Vector138 +#define STM32_I2C3_EVENT_HANDLER Vector188 +#define STM32_I2C3_ERROR_HANDLER Vector18C +#define STM32_I2C4_EVENT_HANDLER Vector1B8 +#define STM32_I2C4_ERROR_HANDLER Vector1BC + +#define STM32_I2C1_EVENT_NUMBER 55 +#define STM32_I2C1_ERROR_NUMBER 56 +#define STM32_I2C2_EVENT_NUMBER 57 +#define STM32_I2C2_ERROR_NUMBER 58 +#define STM32_I2C3_EVENT_NUMBER 88 +#define STM32_I2C3_ERROR_NUMBER 89 +#define STM32_I2C4_EVENT_NUMBER 100 +#define STM32_I2C4_ERROR_NUMBER 101 + +/* + * OCTOSPI unit. + */ +#define STM32_OCTOSPI1_HANDLER Vector170 + +#define STM32_OCTOSPI1_NUMBER 76 + +/* + * SDMMC unit. + */ +#define STM32_SDMMC1_HANDLER Vector178 + +#define STM32_SDMMC1_NUMBER 78 + +/* + * TIM units. + */ +#define STM32_TIM1_BRK_HANDLER VectorE4 +#define STM32_TIM1_UP_HANDLER VectorE8 +#define STM32_TIM1_TRGCO_HANDLER VectorEC +#define STM32_TIM1_CC_HANDLER VectorF0 +#define STM32_TIM2_HANDLER VectorF4 +#define STM32_TIM3_HANDLER VectorF8 +#define STM32_TIM4_HANDLER VectorFC +#define STM32_TIM5_HANDLER Vector100 +#define STM32_TIM6_HANDLER Vector104 +#define STM32_TIM7_HANDLER Vector108 +#define STM32_TIM8_BRK_HANDLER Vector10C +#define STM32_TIM8_UP_HANDLER Vector110 +#define STM32_TIM8_TRGCO_HANDLER Vector114 +#define STM32_TIM8_CC_HANDLER Vector118 +#define STM32_TIM15_HANDLER Vector154 +#define STM32_TIM16_HANDLER Vector158 +#define STM32_TIM17_HANDLER Vector15C + +#define STM32_TIM1_BRK_NUMBER 41 +#define STM32_TIM1_UP_NUMBER 42 +#define STM32_TIM1_TRGCO_NUMBER 43 +#define STM32_TIM1_CC_NUMBER 44 +#define STM32_TIM2_NUMBER 45 +#define STM32_TIM3_NUMBER 46 +#define STM32_TIM4_NUMBER 47 +#define STM32_TIM5_NUMBER 48 +#define STM32_TIM6_NUMBER 49 +#define STM32_TIM7_NUMBER 50 +#define STM32_TIM8_BRK_NUMBER 51 +#define STM32_TIM8_UP_NUMBER 52 +#define STM32_TIM8_TRGCO_NUMBER 53 +#define STM32_TIM8_CC_NUMBER 54 +#define STM32_TIM15_NUMBER 69 +#define STM32_TIM16_NUMBER 70 +#define STM32_TIM17_NUMBER 71 + +/* + * USART/UART units. + */ +#define STM32_USART1_HANDLER Vector134 +#define STM32_USART2_HANDLER Vector138 +#define STM32_USART3_HANDLER Vector13C +#define STM32_UART4_HANDLER Vector140 +#define STM32_UART5_HANDLER Vector144 +#define STM32_LPUART1_HANDLER Vector148 + +#define STM32_USART1_NUMBER 61 +#define STM32_USART2_NUMBER 62 +#define STM32_USART3_NUMBER 63 +#define STM32_UART4_NUMBER 64 +#define STM32_UART5_NUMBER 65 +#define STM32_LPUART1_NUMBER 66 + +/* + * USB/OTG units. + */ +#define STM32_USB_FS_HANDLER Vector164 + +#define STM32_USB_FS_NUMBER 73 + +/* + * FSMC unit. + */ +#define STM32_FSMC_HANDLER Vector16C + +#define STM32_FSMC_NUMBER 75 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L5xx/stm32_rcc.h b/os/hal/ports/STM32/STM32L5xx/stm32_rcc.h index 83e0ee0c72..6302b9e887 100644 --- a/os/hal/ports/STM32/STM32L5xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32L5xx/stm32_rcc.h @@ -1,1254 +1,1254 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L5xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32l5xx.h. - * - * @addtogroup STM32L5xx_RCC - * @{ - */ -#ifndef STM32_RCC_H -#define STM32_RCC_H - -/*===========================================================================*/ -/* 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 (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R1(mask, lp) { \ - RCC->APB1ENR1 |= (mask); \ - if (lp) \ - RCC->APB1SMENR1 |= (mask); \ - else \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccDisableAPB1R1(mask) { \ - RCC->APB1ENR1 &= ~(mask); \ - RCC->APB1SMENR1 &= ~(mask); \ - (void)RCC->APB1SMENR1; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R1). - * - * @param[in] mask APB1 R1 peripherals mask - * - * @api - */ -#define rccResetAPB1R1(mask) { \ - RCC->APB1RSTR1 |= (mask); \ - RCC->APB1RSTR1 &= ~(mask); \ - (void)RCC->APB1RSTR1; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1R2(mask, lp) { \ - RCC->APB1ENR2 |= (mask); \ - if (lp) \ - RCC->APB1SMENR2 |= (mask); \ - else \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccDisableAPB1R2(mask) { \ - RCC->APB1ENR2 &= ~(mask); \ - RCC->APB1SMENR2 &= ~(mask); \ - (void)RCC->APB1SMENR2; \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus (R2). - * - * @param[in] mask APB1 R2 peripherals mask - * - * @api - */ -#define rccResetAPB1R2(mask) { \ - RCC->APB1RSTR2 |= (mask); \ - RCC->APB1RSTR2 &= ~(mask); \ - (void)RCC->APB1RSTR2; \ -} - -/** - * @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->APB2SMENR |= (mask); \ - else \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccDisableAPB2(mask) { \ - RCC->APB2ENR &= ~(mask); \ - RCC->APB2SMENR &= ~(mask); \ - (void)RCC->APB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->APB2RSTR; \ -} - -/** - * @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->AHB1SMENR |= (mask); \ - else \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccDisableAHB1(mask) { \ - RCC->AHB1ENR &= ~(mask); \ - RCC->AHB1SMENR &= ~(mask); \ - (void)RCC->AHB1SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB1RSTR; \ -} - -/** - * @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->AHB2SMENR |= (mask); \ - else \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccDisableAHB2(mask) { \ - RCC->AHB2ENR &= ~(mask); \ - RCC->AHB2SMENR &= ~(mask); \ - (void)RCC->AHB2SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB2RSTR; \ -} - -/** - * @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->AHB3SMENR |= (mask); \ - else \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccDisableAHB3(mask) { \ - RCC->AHB3ENR &= ~(mask); \ - RCC->AHB3SMENR &= ~(mask); \ - (void)RCC->AHB3SMENR; \ -} - -/** - * @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 &= ~(mask); \ - (void)RCC->AHB3RSTR; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC12(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp) - -/** - * @brief Disables the ADC1/ADC2 peripheral clock. - * - * @api - */ -#define rccDisableADC12() rccDisableAHB2(RCC_AHB2ENR_ADCEN) - -/** - * @brief Resets the ADC1/ADC2 peripheral. - * - * @api - */ -#define rccResetADC12() rccResetAHB2(RCC_AHB2RSTR_ADCRST) -/** @} */ - -/** - * @name DAC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DAC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp) - -/** - * @brief Disables the DAC1 peripheral clock. - * - * @api - */ -#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN) - -/** - * @brief Resets the DAC1 peripheral. - * - * @api - */ -#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @api - */ -#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) - -/** - * @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. - * - * @api - */ -#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name DMAMUX peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMAMUX peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp) - -/** - * @brief Disables the DMAMUX peripheral clock. - * - * @api - */ -#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN) - -/** - * @brief Resets the DMAMUX peripheral. - * - * @api - */ -#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @api - */ -#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) -/** @} */ - -/** - * @name FDCAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FDCAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFDCAN1(lp) rccEnableAPB1R2(RCC_APB1ENR2_FDCAN1EN, lp) - -/** - * @brief Disables the FDCAN1 peripheral clock. - * - * @api - */ -#define rccDisableFDCAN1() rccDisableAPB1R2(RCC_APB1ENR2_FDCAN1EN) - -/** - * @brief Resets the FDCAN1 peripheral. - * - * @api - */ -#define rccResetFDCAN1() rccResetAPB1R2(RCC_APB1RSTR2_FDCAN1RST) - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @api - */ -#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @api - */ -#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) - -/** - * @brief Enables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) - -/** - * @brief Disables the I2C3 peripheral clock. - * - * @api - */ -#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) - -/** - * @brief Enables the I2C4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) - -/** - * @brief Disables the I2C4 peripheral clock. - * - * @api - */ -#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) - -/** - * @brief Resets the I2C4 peripheral. - * - * @api - */ -#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) -/** @} */ - -/** - * @name OCTOSPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OCTOSPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOCTOSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_OSPI1EN, lp) - -/** - * @brief Disables the OCTOSPI1 peripheral clock. - * - * @api - */ -#define rccDisableOCTOSPI1() rccDisableAHB3(RCC_AHB3ENR_OSPI1EN) - -/** - * @brief Resets the OCTOSPI1 peripheral. - * - * @api - */ -#define rccResetOCTOSPI1() rccResetAHB3(RCC_AHB3RSTR_OSPI1RST) - -/** - * @name RNG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the RNG peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) - -/** - * @brief Disables the RNG peripheral clock. - * - * @api - */ -#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) - -/** - * @brief Resets the RNG peripheral. - * - * @api - */ -#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) -/** @} */ - -/** - * @name SDMMC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDMMC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp) - -/** - * @brief Disables the SDMMC1 peripheral clock. - * - * @api - */ -#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN) - -/** - * @brief Resets the SDMMC1 peripheral. - * - * @api - */ -#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @api - */ -#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @api - */ -#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @api - */ -#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * - * @api - */ -#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @api - */ -#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @api - */ -#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @api - */ -#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * - * @api - */ -#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @api - */ -#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @api - */ -#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * - * @api - */ -#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM15 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) - -/** - * @brief Disables the TIM15 peripheral clock. - * - * @api - */ -#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) - -/** - * @brief Resets the TIM15 peripheral. - * - * @api - */ -#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) - -/** - * @brief Enables the TIM16 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) - -/** - * @brief Disables the TIM16 peripheral clock. - * - * @api - */ -#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) - -/** - * @brief Resets the TIM16 peripheral. - * - * @api - */ -#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) - -/** - * @brief Enables the TIM17 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) - -/** - * @brief Disables the TIM17 peripheral clock. - * - * @api - */ -#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) - -/** - * @brief Resets the TIM17 peripheral. - * - * @api - */ -#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @api - */ -#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) - -/** - * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @api - */ -#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @api - */ -#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * - * @api - */ -#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * - * @api - */ -#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) - -/** - * @brief Enables the LPUART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) - -/** - * @brief Disables the LPUART1 peripheral clock. - * - * @api - */ -#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @api - */ -#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST) -/** @} */ - -/** - * @name CRC peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the CRC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * - * @api - */ -#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) -/** @} */ - -/** - * @name FSMC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the FSMC peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) - -/** - * @brief Disables the FSMC peripheral clock. - * - * @api - */ -#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) - -/** - * @brief Resets the FSMC peripheral. - * - * @api - */ -#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* STM32_RCC_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L5xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32l5xx.h. + * + * @addtogroup STM32L5xx_RCC + * @{ + */ +#ifndef STM32_RCC_H +#define STM32_RCC_H + +/*===========================================================================*/ +/* 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 (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R1(mask, lp) { \ + RCC->APB1ENR1 |= (mask); \ + if (lp) \ + RCC->APB1SMENR1 |= (mask); \ + else \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccDisableAPB1R1(mask) { \ + RCC->APB1ENR1 &= ~(mask); \ + RCC->APB1SMENR1 &= ~(mask); \ + (void)RCC->APB1SMENR1; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R1). + * + * @param[in] mask APB1 R1 peripherals mask + * + * @api + */ +#define rccResetAPB1R1(mask) { \ + RCC->APB1RSTR1 |= (mask); \ + RCC->APB1RSTR1 &= ~(mask); \ + (void)RCC->APB1RSTR1; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1R2(mask, lp) { \ + RCC->APB1ENR2 |= (mask); \ + if (lp) \ + RCC->APB1SMENR2 |= (mask); \ + else \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccDisableAPB1R2(mask) { \ + RCC->APB1ENR2 &= ~(mask); \ + RCC->APB1SMENR2 &= ~(mask); \ + (void)RCC->APB1SMENR2; \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus (R2). + * + * @param[in] mask APB1 R2 peripherals mask + * + * @api + */ +#define rccResetAPB1R2(mask) { \ + RCC->APB1RSTR2 |= (mask); \ + RCC->APB1RSTR2 &= ~(mask); \ + (void)RCC->APB1RSTR2; \ +} + +/** + * @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->APB2SMENR |= (mask); \ + else \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccDisableAPB2(mask) { \ + RCC->APB2ENR &= ~(mask); \ + RCC->APB2SMENR &= ~(mask); \ + (void)RCC->APB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->APB2RSTR; \ +} + +/** + * @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->AHB1SMENR |= (mask); \ + else \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccDisableAHB1(mask) { \ + RCC->AHB1ENR &= ~(mask); \ + RCC->AHB1SMENR &= ~(mask); \ + (void)RCC->AHB1SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB1RSTR; \ +} + +/** + * @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->AHB2SMENR |= (mask); \ + else \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccDisableAHB2(mask) { \ + RCC->AHB2ENR &= ~(mask); \ + RCC->AHB2SMENR &= ~(mask); \ + (void)RCC->AHB2SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB2RSTR; \ +} + +/** + * @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->AHB3SMENR |= (mask); \ + else \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccDisableAHB3(mask) { \ + RCC->AHB3ENR &= ~(mask); \ + RCC->AHB3SMENR &= ~(mask); \ + (void)RCC->AHB3SMENR; \ +} + +/** + * @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 &= ~(mask); \ + (void)RCC->AHB3RSTR; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC12(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp) + +/** + * @brief Disables the ADC1/ADC2 peripheral clock. + * + * @api + */ +#define rccDisableADC12() rccDisableAHB2(RCC_AHB2ENR_ADCEN) + +/** + * @brief Resets the ADC1/ADC2 peripheral. + * + * @api + */ +#define rccResetADC12() rccResetAHB2(RCC_AHB2RSTR_ADCRST) +/** @} */ + +/** + * @name DAC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DAC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp) + +/** + * @brief Disables the DAC1 peripheral clock. + * + * @api + */ +#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN) + +/** + * @brief Resets the DAC1 peripheral. + * + * @api + */ +#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @api + */ +#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN) + +/** + * @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. + * + * @api + */ +#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name DMAMUX peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMAMUX peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp) + +/** + * @brief Disables the DMAMUX peripheral clock. + * + * @api + */ +#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN) + +/** + * @brief Resets the DMAMUX peripheral. + * + * @api + */ +#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @api + */ +#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST) +/** @} */ + +/** + * @name FDCAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FDCAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFDCAN1(lp) rccEnableAPB1R2(RCC_APB1ENR2_FDCAN1EN, lp) + +/** + * @brief Disables the FDCAN1 peripheral clock. + * + * @api + */ +#define rccDisableFDCAN1() rccDisableAPB1R2(RCC_APB1ENR2_FDCAN1EN) + +/** + * @brief Resets the FDCAN1 peripheral. + * + * @api + */ +#define rccResetFDCAN1() rccResetAPB1R2(RCC_APB1RSTR2_FDCAN1RST) + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @api + */ +#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @api + */ +#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST) + +/** + * @brief Enables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp) + +/** + * @brief Disables the I2C3 peripheral clock. + * + * @api + */ +#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST) + +/** + * @brief Enables the I2C4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp) + +/** + * @brief Disables the I2C4 peripheral clock. + * + * @api + */ +#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN) + +/** + * @brief Resets the I2C4 peripheral. + * + * @api + */ +#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST) +/** @} */ + +/** + * @name OCTOSPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OCTOSPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOCTOSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_OSPI1EN, lp) + +/** + * @brief Disables the OCTOSPI1 peripheral clock. + * + * @api + */ +#define rccDisableOCTOSPI1() rccDisableAHB3(RCC_AHB3ENR_OSPI1EN) + +/** + * @brief Resets the OCTOSPI1 peripheral. + * + * @api + */ +#define rccResetOCTOSPI1() rccResetAHB3(RCC_AHB3RSTR_OSPI1RST) + +/** + * @name RNG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the RNG peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) + +/** + * @brief Disables the RNG peripheral clock. + * + * @api + */ +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +/** + * @brief Resets the RNG peripheral. + * + * @api + */ +#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST) +/** @} */ + +/** + * @name SDMMC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDMMC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp) + +/** + * @brief Disables the SDMMC1 peripheral clock. + * + * @api + */ +#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN) + +/** + * @brief Resets the SDMMC1 peripheral. + * + * @api + */ +#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @api + */ +#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @api + */ +#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @api + */ +#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * + * @api + */ +#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @api + */ +#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @api + */ +#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @api + */ +#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * + * @api + */ +#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @api + */ +#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @api + */ +#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * + * @api + */ +#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM15 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp) + +/** + * @brief Disables the TIM15 peripheral clock. + * + * @api + */ +#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN) + +/** + * @brief Resets the TIM15 peripheral. + * + * @api + */ +#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST) + +/** + * @brief Enables the TIM16 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp) + +/** + * @brief Disables the TIM16 peripheral clock. + * + * @api + */ +#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN) + +/** + * @brief Resets the TIM16 peripheral. + * + * @api + */ +#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST) + +/** + * @brief Enables the TIM17 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp) + +/** + * @brief Disables the TIM17 peripheral clock. + * + * @api + */ +#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN) + +/** + * @brief Resets the TIM17 peripheral. + * + * @api + */ +#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @api + */ +#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN) + +/** + * @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) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @api + */ +#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @api + */ +#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * + * @api + */ +#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * + * @api + */ +#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST) + +/** + * @brief Enables the LPUART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp) + +/** + * @brief Disables the LPUART1 peripheral clock. + * + * @api + */ +#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @api + */ +#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST) +/** @} */ + +/** + * @name CRC peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the CRC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * + * @api + */ +#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST) +/** @} */ + +/** + * @name FSMC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the FSMC peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp) + +/** + * @brief Disables the FSMC peripheral clock. + * + * @api + */ +#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN) + +/** + * @brief Resets the FSMC peripheral. + * + * @api + */ +#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* STM32_RCC_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32L5xx/stm32_registry.h b/os/hal/ports/STM32/STM32L5xx/stm32_registry.h index 1b0b0246ed..ca3169d586 100644 --- a/os/hal/ports/STM32/STM32L5xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L5xx/stm32_registry.h @@ -1,277 +1,277 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32L5xx/stm32_registry.h - * @brief STM32L5xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef STM32_REGISTRY_H -#define STM32_REGISTRY_H - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32L5xx capabilities - * @{ - */ - -/*===========================================================================*/ -/* Common. */ -/*===========================================================================*/ - -/* RNG attributes.*/ -#define STM32_HAS_RNG1 TRUE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE -#define STM32_RTC_NUM_ALARMS 2 -#define STM32_RTC_STORAGE_SIZE 128 -#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 -#define STM32_RTC_WKUP_HANDLER Vector4C -#define STM32_RTC_ALARM_HANDLER VectorE4 -#define STM32_RTC_TAMP_STAMP_NUMBER 2 -#define STM32_RTC_WKUP_NUMBER 3 -#define STM32_RTC_ALARM_NUMBER 41 -#define STM32_RTC_ALARM_EXTI 18 -#define STM32_RTC_TAMP_STAMP_EXTI 19 -#define STM32_RTC_WKUP_EXTI 20 -#define STM32_RTC_IRQ_ENABLE() do { \ - nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ - nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ - nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ -} while (false) - -#if defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \ - defined(__DOXYGEN__) -#define STM32_HAS_HASH1 TRUE -#define STM32_HAS_CRYP1 TRUE -#else -#define STM32_HAS_HASH1 FALSE -#define STM32_HAS_CRYP1 FALSE -#endif - -/*===========================================================================*/ -/* STM32L4yyxx+. */ -/*===========================================================================*/ - -#if defined(STM32L552xx) || defined(__DOXYGEN__) - -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 TRUE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE -#define STM32_HAS_CAN3 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC1_CH1 TRUE -#define STM32_HAS_DAC1_CH2 TRUE -#define STM32_HAS_DAC2_CH1 FALSE -#define STM32_HAS_DAC2_CH2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_DMA_SUPPORTS_DMAMUX TRUE -#define STM32_DMA_SUPPORTS_CSELR FALSE -#define STM32_DMA1_NUM_CHANNELS 8 -#define STM32_DMA2_NUM_CHANNELS 8 - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_LINES 43 -#define STM32_EXTI_IMR1_MASK 0xFF9E0000U -#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U - -/* FDCAN attributes.*/ - -/* Flash attributes.*/ -#define STM32_FLASH_NUMBER_OF_BANKS 2 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI FALSE -#define STM32_HAS_GPIOJ FALSE -#define STM32_HAS_GPIOK FALSE -#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ - RCC_AHB2ENR_GPIOBEN | \ - RCC_AHB2ENR_GPIOCEN | \ - RCC_AHB2ENR_GPIODEN | \ - RCC_AHB2ENR_GPIOEEN | \ - RCC_AHB2ENR_GPIOFEN | \ - RCC_AHB2ENR_GPIOGEN | \ - RCC_AHB2ENR_GPIOHEN) - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_HAS_I2C2 TRUE -#define STM32_HAS_I2C3 TRUE -#define STM32_HAS_I2C4 TRUE - -/* OCTOSPI attributes.*/ -#define STM32_HAS_OCTOSPI1 TRUE -#define STM32_HAS_OCTOSPI2 FALSE - -/* QUADSPI attributes.*/ -#define STM32_HAS_QUADSPI1 FALSE - -/* SDMMC attributes.*/ -#define STM32_HAS_SDMMC1 TRUE -#define STM32_HAS_SDMMC2 FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_SUPPORTS_I2S FALSE - -#define STM32_HAS_SPI4 FALSE -#define STM32_HAS_SPI5 FALSE -#define STM32_HAS_SPI6 FALSE - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 2 - -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE -#define STM32_HAS_TIM20 FALSE -#define STM32_HAS_TIM21 FALSE -#define STM32_HAS_TIM22 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_HAS_USART2 TRUE -#define STM32_HAS_USART3 TRUE -#define STM32_HAS_UART4 TRUE -#define STM32_HAS_UART5 TRUE -#define STM32_HAS_LPUART1 TRUE -#define STM32_HAS_USART6 FALSE -#define STM32_HAS_UART7 FALSE -#define STM32_HAS_UART8 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_USB_ACCESS_SCHEME_2x16 TRUE -#define STM32_USB_PMA_SIZE 1024 -#define STM32_USB_HAS_BCDR FALSE - -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE - -/* IWDG attributes.*/ -#define STM32_HAS_IWDG TRUE -#define STM32_IWDG_IS_WINDOWED TRUE - -/* LTDC attributes.*/ -#define STM32_HAS_LTDC FALSE - -/* DMA2D attributes.*/ -#define STM32_HAS_DMA2D FALSE - -/* FSMC attributes.*/ -#define STM32_HAS_FSMC TRUE -#define STM32_FSMC_IS_FMC FALSE - -/* CRC attributes.*/ -#define STM32_HAS_CRC TRUE -#define STM32_CRC_PROGRAMMABLE TRUE - -/* DCMI attributes.*/ -#define STM32_HAS_DCMI TRUE - -#endif /* defined(STM32L4R5xx) || defined(STM32L4R7xx) || - defined(STM32L4R9xx) || defined(STM32L4S5xx) || - defined(STM32L4S7xx) || defined(STM32L4S9xx) */ - -/** @} */ - -#endif /* STM32_REGISTRY_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32L5xx/stm32_registry.h + * @brief STM32L5xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef STM32_REGISTRY_H +#define STM32_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32L5xx capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/* RNG attributes.*/ +#define STM32_HAS_RNG1 TRUE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE +#define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 +#define STM32_RTC_TAMP_STAMP_HANDLER Vector48 +#define STM32_RTC_WKUP_HANDLER Vector4C +#define STM32_RTC_ALARM_HANDLER VectorE4 +#define STM32_RTC_TAMP_STAMP_NUMBER 2 +#define STM32_RTC_WKUP_NUMBER 3 +#define STM32_RTC_ALARM_NUMBER 41 +#define STM32_RTC_ALARM_EXTI 18 +#define STM32_RTC_TAMP_STAMP_EXTI 19 +#define STM32_RTC_WKUP_EXTI 20 +#define STM32_RTC_IRQ_ENABLE() do { \ + nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \ + nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \ + nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \ +} while (false) + +#if defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \ + defined(__DOXYGEN__) +#define STM32_HAS_HASH1 TRUE +#define STM32_HAS_CRYP1 TRUE +#else +#define STM32_HAS_HASH1 FALSE +#define STM32_HAS_CRYP1 FALSE +#endif + +/*===========================================================================*/ +/* STM32L4yyxx+. */ +/*===========================================================================*/ + +#if defined(STM32L552xx) || defined(__DOXYGEN__) + +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 TRUE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE +#define STM32_HAS_CAN3 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC1_CH1 TRUE +#define STM32_HAS_DAC1_CH2 TRUE +#define STM32_HAS_DAC2_CH1 FALSE +#define STM32_HAS_DAC2_CH2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_DMA_SUPPORTS_DMAMUX TRUE +#define STM32_DMA_SUPPORTS_CSELR FALSE +#define STM32_DMA1_NUM_CHANNELS 8 +#define STM32_DMA2_NUM_CHANNELS 8 + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_LINES 43 +#define STM32_EXTI_IMR1_MASK 0xFF9E0000U +#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U + +/* FDCAN attributes.*/ + +/* Flash attributes.*/ +#define STM32_FLASH_NUMBER_OF_BANKS 2 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI FALSE +#define STM32_HAS_GPIOJ FALSE +#define STM32_HAS_GPIOK FALSE +#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \ + RCC_AHB2ENR_GPIOBEN | \ + RCC_AHB2ENR_GPIOCEN | \ + RCC_AHB2ENR_GPIODEN | \ + RCC_AHB2ENR_GPIOEEN | \ + RCC_AHB2ENR_GPIOFEN | \ + RCC_AHB2ENR_GPIOGEN | \ + RCC_AHB2ENR_GPIOHEN) + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_HAS_I2C2 TRUE +#define STM32_HAS_I2C3 TRUE +#define STM32_HAS_I2C4 TRUE + +/* OCTOSPI attributes.*/ +#define STM32_HAS_OCTOSPI1 TRUE +#define STM32_HAS_OCTOSPI2 FALSE + +/* QUADSPI attributes.*/ +#define STM32_HAS_QUADSPI1 FALSE + +/* SDMMC attributes.*/ +#define STM32_HAS_SDMMC1 TRUE +#define STM32_HAS_SDMMC2 FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_SUPPORTS_I2S FALSE + +#define STM32_HAS_SPI4 FALSE +#define STM32_HAS_SPI5 FALSE +#define STM32_HAS_SPI6 FALSE + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 2 + +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE +#define STM32_HAS_TIM20 FALSE +#define STM32_HAS_TIM21 FALSE +#define STM32_HAS_TIM22 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_HAS_USART2 TRUE +#define STM32_HAS_USART3 TRUE +#define STM32_HAS_UART4 TRUE +#define STM32_HAS_UART5 TRUE +#define STM32_HAS_LPUART1 TRUE +#define STM32_HAS_USART6 FALSE +#define STM32_HAS_UART7 FALSE +#define STM32_HAS_UART8 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_USB_ACCESS_SCHEME_2x16 TRUE +#define STM32_USB_PMA_SIZE 1024 +#define STM32_USB_HAS_BCDR FALSE + +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE + +/* IWDG attributes.*/ +#define STM32_HAS_IWDG TRUE +#define STM32_IWDG_IS_WINDOWED TRUE + +/* LTDC attributes.*/ +#define STM32_HAS_LTDC FALSE + +/* DMA2D attributes.*/ +#define STM32_HAS_DMA2D FALSE + +/* FSMC attributes.*/ +#define STM32_HAS_FSMC TRUE +#define STM32_FSMC_IS_FMC FALSE + +/* CRC attributes.*/ +#define STM32_HAS_CRC TRUE +#define STM32_CRC_PROGRAMMABLE TRUE + +/* DCMI attributes.*/ +#define STM32_HAS_DCMI TRUE + +#endif /* defined(STM32L4R5xx) || defined(STM32L4R7xx) || + defined(STM32L4R9xx) || defined(STM32L4S5xx) || + defined(STM32L4S7xx) || defined(STM32L4S9xx) */ + +/** @} */ + +#endif /* STM32_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/todo.txt b/os/hal/ports/STM32/todo.txt index c30cafcd14..5dc50c8689 100644 --- a/os/hal/ports/STM32/todo.txt +++ b/os/hal/ports/STM32/todo.txt @@ -1,4 +1,4 @@ -- BOFF handling in DACv1. -- Oversampling support for ADCv1 and ADCv3. -- Implement missing ICU/PWM/GPT/ST units using shared IRQ handlers. -- Implement I2S driver over SAI interfaces. +- BOFF handling in DACv1. +- Oversampling support for ADCv1 and ADCv3. +- Implement missing ICU/PWM/GPT/ST units using shared IRQ handlers. +- Implement I2S driver over SAI interfaces.